c-嵌套中的Paralelized执行,用于使用Cilk



我正在尝试实现一个操纵矩阵的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为什么以及如何破坏我的顺序代码;或者更确切地说,我该如何阻止它这样做?

如果您感兴趣的话,实际的代码当然也是可用的。然而,这个项目是为一个大学班级设计的,因此会受到其他发现这个帖子的学生的抄袭,这就是为什么我不愿意公开分享它。

**更新:

正如建议的那样,我尝试只使用一个工作线程来运行算法,有效地使cilk实现按顺序进行。令人惊讶的是,这个确实做得很好。然而,一旦我将工作人员的数量更改为两个,熟悉的错误就会再次出现。

不过,我不认为这种行为是由比赛条件引起的。由于工作矩阵在每次迭代后都会发生变化,并且调用cilk_sync,因此实际上不存在关键部分。并非所有线程都依赖于其他线程在同一迭代中编写的数据。

我将尝试的下一步是尝试cilkplus编译器的其他版本,看看这是否是他们的错误。

关于cilk_for中的浮点异常,在cilk Plus运行时的某些版本中已经修复了一些问题。你有可能使用了一个过时的版本吗?

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

此外,产生了哪些具体的警告信息?旧版本的Cilk Plus GCC中会出现一些"未初始化变量"警告,我认为这些警告是虚假的。

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

作为初始化的一部分,它计算一个"粒度",它将把你的范围划分为最小大小。默认情况下,这是loopRange/8P,其中P是核心数。

一个有趣的实验是将Cilk工人的数量设置为1。当您这样做时,所有cilk_for机制都会被过度化,但因为只有一个工作者,所以不会有任何东西被盗。

另一种可能性是尝试在Cilkscreen(Cilk种族检测器)下运行代码。不幸的是,只有GCC的cilkplus分支生成Cilkscreen所需的注释。您可以选择使用Intel命令行,或者尝试使用GCC 4.9的cilkplus分支。cilkplus.org网站上有关于如何下载和构建代码的说明。

相关内容

  • 没有找到相关文章

最新更新