我正在使用带有卸载的cilk plus对Xeon phi进行一些性能测试。
在一个简单的矢量添加程序中,我有两种方法:
-
在Xeon phi:中使用cilk_for将任务拆分到不同的线程
__declspec(target(mic)) void vector_add(double *A,double *B,double *C, int vector_size) { _Cilk_for(int i=0;i<vector_size;i++) { C[i] += A[i] + B[i]; } } double *A,*B,*C; //allocating and initializing A, B ,C using malloc..... #pragma offload target(mic:0) in(B:length(vector_size)) in(A:length(vector_size)) in(C:length(vector_size)) in(vector_size ) { vector_add(A,B,C,vector_size); }
-
使用矢量标注:
double *A,*B,*C; //allocating and initializing A, B ,C using malloc..... #pragma offload target(mic:0) in(B:length(vector_size)) in(A:length(vector_size)) in(C:length(vector_size)) //in(vector_size ) //signal(offload0) { C[0:vector_size] = A[0:vector_size]+B[0:vector_size]; }
我的测试显示,在xeon phi上,第一种方法比第二种方法快约10倍。当我不卸载并在Xeon E5主机CPU上运行它时,也会发生同样的情况。
首先我想知道我的理解是否正确:
第一种方法仅利用XEON phi中的线程并行性(60个核*4个线程)。但不会执行矢量运算。
第二种方法只利用矢量化,即只在一个线程中运行此代码,并使用SIMD(IMCI)指令。
其次,我想知道写这篇文章的正确方法是什么,这样它既可以将任务拆分到不同的线程,又可以在Xeon phi上使用矢量指令?
提前谢谢。
实际上,如果您查看编译器生成的优化报告(-opt report),或者查看VTune输出(如果有),您可能会感到惊讶。正如您所推测的,您的第二个示例只进行矢量化。然而,除了并行化之外,第一个示例还可以向量化。请记住,_Cilk_for不是分发单独的迭代,而是可以在某些情况下向量化的迭代块。
为了更好地控制,您可以尝试使用嵌套循环来显式地分离并行循环和矢量循环,或者使用粒度大小来改变线程在任何给定时间必须处理的工作量或多个不同的杂注。
对于专门针对英特尔至强Phi协处理器的优化建议,我喜欢向人们介绍https://software.intel.com/en-us/articles/programming-and-compiling-for-intel-many-integrated-core-architecture,但我想你可能会觉得有些太基础了。尽管如此,如果你想四处挖掘。。。。