Почему этот код OpenMP работает в Linux, но не в Windows? - PullRequest
1 голос
/ 16 мая 2019

Редактировать: решено! Windows ограничивает размер стека тем, что мой буфер не помещается; Linux не (кроме того, я обращался к памяти за пределами моего массива ... упс). Используя gcc, вы можете установить размер стека следующим образом: gcc -Wl --stack,N [your other flags n stuff] где N - размер стека в байтах. Окончательная рабочая команда компиляции: gcc -Wl --stack,8000000 -fopenmp openmp.c -o openmp

Интересно, что функция rand () производит меньшие шаблоны, чем в Linux, потому что я вижу шаблоны (мозаику) в сгенерированном шуме в Windows, но не в Linux. Как всегда, если вам нужно, чтобы он был абсолютно случайным, используйте криптографически безопасную функцию rand.

Предварительное редактирование:

Этот фрагмент кода должен создать буфер случайного шума, а затем записать его в файл. Он работает на Linux (Ubuntu 19), но не на Windows (8.1).

Сообщение об ошибке:

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;
}

Ответы [ 2 ]

4 голосов
/ 16 мая 2019

Локальной переменной buffer требуется 1920 *1080* 3 (6 220 800) байтов пространства.Это больше, чем размер стека по умолчанию в приложении Windows.

Если вы использовали инструменты Microsoft, вы можете использовать опцию компоновщика /STACK, чтобы указать больший стек.

С помощью цепочки инструментов GCC вы можете использовать опцию --stack,8000000 для установки большего размера стека.

Или вы можете динамически распределять пространство для buffer, используя malloc.

Третьим вариантом является использование инструмента editbin для указания размера после сборки исполняемого файла.

2 голосов
/ 16 мая 2019

В

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

вы получаете доступ к buffer за пределами.Самые высокие действительные индексы для buffer: w - 1 и 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]);
...