Intel Cilk Plus阵列表示法的奇怪复制行为

时间:2014-02-25 05:40:17

标签: arrays parallel-processing cilk cilk-plus

我正在使用英特尔Cilk Plus阵列表示法来练习矢量编程。 但是,我遇到了阵列分配的奇怪复制行为。

要解决的问题是并行前缀。输入D,输出P.

//错误的结果代码。在Intel icc 14.0.2上进行了测试。

void vec_prefix(int n, int D[n], int P[n]) {
  P[0:n] = D[0:n]; //initial copy
  int bound=1;
  int * Buf1 = _mm_malloc(n*sizeof(int), 16);
  int * Buf2 = _mm_malloc(n*sizeof(int), 16);

  while(bound<n){
    Buf1[0:n-bound] = P[0:n-bound];
    Buf2[0:n-bound] = P[bound:n-bound];
    //printf("WHY??\n");  //Add this fence, the result will be correct.
    P[bound:n-bound] = Buf1[0:n-bound] + Buf2[0:n-bound];
    bound<<=1;
  }
  _mm_free(Buf1); _mm_free(Buf2);
}

如果我删除“printf”行的注释,结果是正确的。否则,错了。 但如果所有副本都遵循英特尔文档中的描述,则代码应该是正确的。

似乎没有内存栅栏,前两行的Buf1 / Buf2副本没有完成,后面的添加操作使用了一些不稳定的值。 或者,编译器优化器只使用复制传播来移除副本,并创建“P [bound:n-bound] = P [0:n-bound] + P [bound:n-bound]”。这在英特尔的文档中是未定义的。

//更正结果代码

void vec_prefix(int n, int D[n], int P[n]) {
  P[0:n] = D[0:n]; //initial copy
  int bound=1;
  int * Buf1 = _mm_malloc(n*sizeof(int), 16);

  while(bound<n){
    //direct copy part
    Buf1[0:bound] = P[0:bound];
    //add part
    Buf1[bound:n-bound] = P[bound:n-bound] + P[0:n-bound];
    //copy back
    P[0:n] = Buf1[0:n];
    bound<<=1;
  }
  _mm_free(Buf1);
}

参考:英特尔的文件

1 个答案:

答案 0 :(得分:0)

您的代码对我来说是正确的。不需要“围栏”。我向英特尔编译器组提交了一份内部错误报告,其中包含所有输入的示例。谢谢你的例子。

如果编译器工作正常,您甚至可以将while循环缩短为:

while(bound<n){
    Buf1[0:n-bound] = P[0:n-bound];
    P[bound:n-bound] = Buf1[0:n-bound] + P[bound:n-bound];
    bound<<=1;
}

第二个数组部分分配是可以的,因为P的重叠是完全正确的。 Alas icc也展示了这个例子的错误。