我正在尝试将 OpenMP 并行化添加到工作代码中(仅添加到单个 for
循环),但是我无法消除段错误。问题出在这一行:
pos += sprintf(com + pos, "%d ", i);
com
是一个字符数组,我尝试将其定义为 char com[255]
或 char *com = malloc(255*sizeof(char) )
,在 for
循环内部和之前。当我在循环之前定义 com
时,我将 private(com)
添加到 #pragma omp parallel for
指令中。我还尝试初始化它并使用 firstprivate
。 (pos
是一个整数,初始化为0
)
当我不添加 -fopenmp
时,一切正常,但使用 -fopenmp
时会出现段错误。我错过了什么?
最佳答案
段错误来自于多个线程同时更新 pos
的值,因此将其设置为某个值,将 com + pos
转换为指向的指针超出或之前为 com
分配的内存。并行化此类循环的正确方法是连接私有(private)字符串中的值,然后以有序方式连接私有(private)字符串:
char com[255];
int pos = 0;
#pragma omp parallel
{
char mycom[255];
int mypos = 0;
#pragma omp for schedule(static) nowait
for (int i = 0; i < N; i++)
mypos += sprintf(mycom + mypos, "%d ", i);
// Concatenate the strings in an ordered fashion
#pragma omp for schedule(static) ordered
for (int i = 0; i < omp_get_num_threads(); i++)
{
#pragma omp ordered
pos += sprintf(com + pos, "%s", mycom);
}
}
有序
结构可确保正确的同步,因此不需要关键
。为了保证每个线程处理迭代空间的单个连续部分,schedule(static)
的使用非常重要。
关于c - OpenMP 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29247593/