嵌套使用Cilk的paralellized执行

时间:2015-12-13 15:23:11

标签: c cilk cilk-plus

我试图实现操纵矩阵的2D模板算法。对于矩阵中的每个字段,要将其上方,下方,左侧和右侧的字段相加并除以4以计算新值。对于给定的矩阵,该过程可以多次迭代。

程序用C语言编写,并用cilkplus gcc二进制文件编译。

**编辑:我认为您可能对编译器标志感兴趣:

~/cilkplus/bin/gcc -fcilkplus -lcilkrts -pedantic-errors -g -Wall -std=gnu11 -O3  `pkg-config --cflags glib-2.0 gsl`   -c -o sal_cilk_tst.o sal_cilk_tst.c

请注意, real 代码涉及一些指针算法以保持一致。顺序实现有效。我在这里省略了这些步骤以增强可理解性。

伪代码看起来像这样(没有边缘案例处理):

for(int i = 0; i < iterations; i++){
   for(int j = 0; j < matrix.width; j++){
      for(int k = 0; k < matrix.height; k++){
         result_ matrix[j][k] = (matrix[j-1][k] + 
                                 matrix[j+1][k] +
                                 matrix[j]  [k+1] +
                                 matrix[j]  [k-1]) / 4;
      }
   }
   matrix = result_matrix;
}

然后将模板计算本身移动到函数apply_stencil(...)

for(int i = 0; i < iterations; i++){
   for(int j = 0; j < matrix.width; j++){
      for(int k = 0; k < matrix.height; k++){
         apply_stencil(matrix, result_matrix, j, k);
      }
   }
   matrix = result_matrix;
}

尝试并行化:

for(int i = 0; i < iterations; i++){
   for(int j = 0; j < matrix.width; j++){
      cilk_for(int k = 0; k < matrix.height; k++){ /* <--- */
         apply_stencil(matrix, result_matrix, j, k);
      }
   }
   matrix = result_matrix;
}

此版本编译时没有错误/警告,但直接执行时会生成Floating point exception。如果您想知道:哪个for循环被制作成cilk_for循环并不重要。所有配置(除了没有cilk_for)都会产生相同的错误。

可能的其他方法:

for(int i = 0; i < iterations; i++){
   for(int j = 0; j < matrix.width; j++){
      for(int k = 0; k < matrix.height; k++){
         cilk_spawn apply_stencil(matrix, result_matrix, j, k); /* <--- */
      }
   }
   cilk_sync; /* <--- */
   matrix = result_matrix;
}

编译时会产生3个警告:i, jk似乎未初始化。 尝试执行时,执行matrix = result_matrix;步骤的函数似乎未定义。

现在提出实际问题:Cilk为什么以及如何破坏我的顺序代码;或者我怎样才能阻止它这样做呢?

如果您感兴趣,实际代码当然也可用。然而,这个项目是针对一个大学课程,因此受到其他学生的抄袭,这些学生找到了这个帖子,这就是为什么我不愿意公开分享它。

**更新:

正如所建议的那样,我尝试仅使用1个工作线程运行算法,从而有效地使cilk实现顺序执行。这个确实,令人惊讶的是,工作得很好。但是,只要我将工人数量更改为2,就会返回熟悉的错误。

我不认为这种行为是由种族条件引起的。由于工作矩阵在每次迭代后都会更改,并且cilk_sync被调用,因此实际上没有关键部分。所有线程都不依赖于其他人在同一次迭代中写入的数据。

我将尝试的下一步是尝试其他版本的cilkplus编译器,看看它是否可能是一个错误。

2 个答案:

答案 0 :(得分:1)

关于cilk_for中的浮点异常,在某些版本的Cilk Plus运行时中存在一些已修复的问题。您是否可能使用过时的版本?

https://software.intel.com/en-us/forums/intel-cilk-plus/topic/558825

此外,产生的具体警告信息是什么?有一些&#34;未初始化的变量&#34;旧版Cilk Plus GCC发生的警告,我认为是虚假的警告。

答案 1 :(得分:0)

Cilk运行时使用递归分治算法来并行化循环。从本质上讲,它将范围分成两半,递归地调用自己两次,产生一半并调用一半。

作为初始化的一部分,它计算一个&#34;粒度&#34;这是最小尺寸的大小,它会打破你的范围。默认情况下,即loopRange / 8P,其中P是核心数。

一个有趣的实验是将Cilk工作者的数量设置为1.当你这样做时,所有的cilk_for机制都被超越了,但因为只有1个工人,所以没有任何东西被盗。

另一种可能性是尝试在Cilkscreen下运行您的代码 - Cilk竞赛检测器。不幸的是,只有GCC的cilkplus分支生成了Cilkscreen所需的注释。您的选择是使用英特尔commpiler,或尝试使用GCC 4.9的cilkplus分支。有关如何下拉代码并构建代码的说明,请参见cilkplus.org website