首页 > 解决方案 > 这是C中“限制”的正确使用吗?

问题描述

目前我正在学习并行编程。我有以下需要并行化的循环。

for(i=0; i<n/2; i++)
   a[i] = a[i+1] + a[2*i]

如果我按顺序运行它没有问题,但如果我想并行运行它,就会发生数据重复。为避免这种情况,我想将要“读取”的信息存储在单独的变量中,例如 b。

那么代码将是:

b = a;
#pragma omp parallel for private(i)
for(i=0; i<n/2; i++)
  a[i] = b[i+1] + b[2*i];

但这里是我开始怀疑的部分。可能变量 b 将指向与 a 相同的内存位置。所以第二个代码块将与第一个代码块完全一样。包括我试图避免的复发。

我用 * retric {variable} 尝试了一些东西。不幸的是,我真的找不到正确的文档。

我的问题:

我是否可以通过如下编写代码来避免数据重复?

int *restrict b;
int *restrict a;
b = a;

#pragma omp parallel for private(i)
for(i=0; i<n/2; i++)
   a[i] = b[i+1] + b[2*i];

如果不是,那么实现这一目标的正确方法是什么?

谢谢, 特尔

标签: cparallel-processingopenmp

解决方案


在您提出的代码中:

int *restrict b;
int *restrict a;
b = a;

ato的分配b违反了restrict要求。这需要a并且b不指向相同的内存,但它们显然确实指向相同的内存。这是不安全的。

为了安全起见,您必须制作一个单独分配的数组副本。你可以这样做:

int *b = malloc(n * size of(*b));
…error check…;
memmove(b, a, n *sizeof(*b));
…revised loop using a and b…
free(b);

我总是使用memmove()它,因为它总是正确的,处理重叠的副本。在这种情况下,使用它是合法的,memcpy()因为分配的空间b将与空间分开a。如果新分配的空间完全b重叠,则系统将被破坏a,假设指针a有效。如果有重叠,问题就在于a分配和释放——a一个指向已释放内存的悬空指针也是如此(根本不应该被使用),并且b巧合地分配在a以前分配旧内存的地方。总的来说,这不是一个值得担心的问题。(使用memmove()没有帮助,如果a是一个悬空指针,但如果给定有效指针,它总是安全的,即使内存区域重叠。)


推荐阅读