Why does this OpenMP code work on Linux, but not Windows?

1

Edit: solved! Windows limits the stack size to where my buffer does not fit; linux does not (additionaly I was accessing memory outside of my array... oops). Using gcc, you can set the stack size like so: gcc -Wl --stack,N [your other flags n stuff] where N is the size of the stack in bytes. Final working compile command: gcc -Wl --stack,8000000 -fopenmp openmp.c -o openmp

An interesting sidenote is that the rand() function seems to produce smaller patterns than in Linux, because I can see patterns (tiling) in the generated noise on Windows, but not on Linux. As always, if you need it to be absolutely random, use a cryptographically secure rand function.

Pre edit:

This piece of code is supposed to make a screenbuffer of randomnoise, then write that to a file. It works on linux (ubuntu 19) but not on windows (8.1).

The error message:

Unhandled exception at 0x0000000000413C46 in openmp.exe:
0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x0000000000043D50).
0000000000413C46  or          qword ptr [rcx],0  

// gcc -fopenmp openmp.c -o openmp // ./openmp

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#include <stdint.h>

int main(int argc, char **argv)
{
  int w = 1920;
  int h = 1080;

  int thread_id, nloops;

  unsigned char buffer[w][h][3]; // 1920 x 1080 pixels, 3 channels
  printf("Did setup\n");
  #pragma omp parallel private(thread_id, nloops)
  {
    nloops = 0;
    thread_id = omp_get_thread_num();

    printf("Thread %d started\n", thread_id);

    #pragma omp for
    for (int x = 0; x < w; x++){
      for (int y = 0; y < h; y++){
        nloops++;
        unsigned char r = rand();
        unsigned char g = rand();
        unsigned char b = rand();
        buffer[x][y][0] = r;
        buffer[x][y][1] = g;
        buffer[x][y][2] = b;
      }
    }

    printf("Thread %d performed %d iterations of the loop.\n", thread_id, nloops);
  }

  FILE* image = fopen("render.ppm","w");
  fprintf(image, "P3\n%d %d\n%d\n", w, h, 255);
  for (int x = 0; x < w; x++){
    for (int y = 0; y < h-1; y++){
      fprintf(image, "%d %d %d ", buffer[x][y][0], buffer[x][y][1], buffer[x][y][2]);
    }
    fprintf(image, "%d %d %d\n", buffer[w][h][0], buffer[w][h][1], buffer[w][h][2]);
  }

  printf("%fmb\n", ((float)sizeof(buffer))/1000000);

  return 0;
}
c
arrays
openmp
variable-length-array
asked on Stack Overflow May 16, 2019 by AnnoyinC • edited May 16, 2019 by AnnoyinC

2 Answers

4

The local buffer variable wants 1920 * 1080 * 3 (6,220,800) bytes of space. This is more than the default stack size on a Windows application.

If you were using the Microsoft tools, you could use the /STACK linker option to specify a larger stack.

With the GCC toolchain, you can use the --stack,8000000 option to set a larger stack size.

Or you can dynamically allocate space for buffer using malloc.

A third alternative is to use the editbin tool to specify the size after the executable is built.

answered on Stack Overflow May 16, 2019 by 1201ProgramAlarm • edited May 16, 2019 by 1201ProgramAlarm
2

In

fprintf(image, "%d %d %d\n", buffer[w][h][0], buffer[w][h][1], buffer[w][h][2]);

you are accessing buffer out of bounds. The highest valid indices for buffer are w - 1 and h - 1:

fprintf(image, "%d %d %d\n", buffer[w - 1][h - 1][0], buffer[w - 1][h - 1][1], buffer[w - 1][h - 1][2]);
answered on Stack Overflow May 16, 2019 by Swordfish

User contributions licensed under CC BY-SA 3.0