【问题标题】:The strange copy behavior of Intel Cilk Plus array notation英特尔 Cilk Plus 数组符号的奇怪复制行为
【发布时间】:2014-03-27 04:00:10
【问题描述】:

我正在使用 Intel 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拷贝没有完成,后面的add操作使用了一些不稳定的值。 或者,编译器优化器只是使用复制传播来删除副本,并创建“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);
}

参考:英特尔的文档

【问题讨论】:

    标签: arrays parallel-processing cilk cilk-plus


    【解决方案1】:

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

    如果编译器工作正常,您甚至可以将 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 的重叠是完全正确的。唉 icc 在这个例子中也展示了它的错误。

    【讨论】:

    • 感谢您的帮助!
    猜你喜欢
    • 2015-04-08
    • 1970-01-01
    • 2016-06-27
    • 2014-09-30
    • 1970-01-01
    • 2013-08-13
    • 2016-10-27
    • 1970-01-01
    • 2019-12-06
    相关资源
    最近更新 更多