【问题标题】:Why does this OpenMP code work on Linux, but not Windows?为什么这个 OpenMP 代码可以在 Linux 上运行,而在 Windows 上不行?
【发布时间】:2019-10-04 03:32:38
【问题描述】:

编辑:解决了! 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;
}

【问题讨论】:

    标签: c arrays openmp variable-length-array


    【解决方案1】:

    本地 buffer 变量需要 1920 * 1080 * 3 (6,220,800) 字节的空间。这超过了 Windows 应用程序的默认堆栈大小。

    如果您使用的是 Microsoft 工具,则可以使用 /STACK 链接器选项来指定更大的堆栈。

    使用 GCC 工具链,您可以使用 --stack,8000000 选项来设置更大的堆栈大小。

    或者您可以使用mallocbuffer 动态分配空间。

    第三种选择是使用editbin 工具来指定构建可执行文件后的大小。

    【讨论】:

    • 这似乎是最有可能的。如何在 C 文件中使用 /STACK?每个人都在谈论“属性>配置属性->链接器->系统->堆栈保留大小”但是,这是哪里????我正在使用 Sublime Text 编辑器
    • @AnnoyinC 那是在 Visual Studio IDE 中。如果你不使用它,那么你可以把它放在命令行上,或者作为link 命令的一部分,或者在传递给CL(编译器)的/link 选项之后。
    • 我正在使用 gcc。我发现“gcc -Wl,--stack,8000000”有效。这将堆栈大小设置为 8mb,这很容易容纳我的 6.2mb 数组。感谢您为我指明这个方向,我的程序现在可以编译并运行了!
    【解决方案2】:

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

    您正在越界访问bufferbuffer 的最高有效索引是 w - 1h - 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]);
    

    【讨论】:

    • 哦,当然。它在 linux 上工作的原因是因为它编译成稍微不同的东西,不会引发错误。我没有在错误的内存位置看到来自随机数据的随机噪声的原因是因为整个图像无论如何都是噪声。谢谢!
    • 2:我按照您的建议编辑了该行,但弹出相同的错误。当我使用 vs2019 调试时,然后按继续,它给我一个访问冲突写入位置错误,但我不确定这次是什么。
    • @AnnoyinC 抱歉,我第一眼看到的就这些。
    猜你喜欢
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    • 2017-03-28
    相关资源
    最近更新 更多