Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C omp simd缩减无加速_C_Performance_Parallel Processing_Openmp_Simd - Fatal编程技术网

C omp simd缩减无加速

C omp simd缩减无加速,c,performance,parallel-processing,openmp,simd,C,Performance,Parallel Processing,Openmp,Simd,我试图使用矢量化(openmp simd)来加速矩阵乘法。为了利用矢量化,我转置了第二个矩阵(使变化最快的索引遍历连续内存)。我正在3000 x 3000阵列上运行测试。因为我无法测量有和没有open-mp-pragma时的墙时间差异,所以我想确认,对于我正在乘法的单个阵列,我实际上得到了一个加速比(事实并非如此)。因此,我插入了一些大小相同的虚拟数组,以检查它们是否得到了SIMD的加速(至少在使用reduction子句时是这样) 现在我的问题是,阻碍SIMD加速的问题是什么?我唯一的猜测是,这

我试图使用矢量化(openmp simd)来加速矩阵乘法。为了利用矢量化,我转置了第二个矩阵(使变化最快的索引遍历连续内存)。我正在3000 x 3000阵列上运行测试。因为我无法测量有和没有open-mp-pragma时的墙时间差异,所以我想确认,对于我正在乘法的单个阵列,我实际上得到了一个加速比(事实并非如此)。因此,我插入了一些大小相同的虚拟数组,以检查它们是否得到了SIMD的加速(至少在使用reduction子句时是这样)

现在我的问题是,阻碍SIMD加速的问题是什么?我唯一的猜测是,这一定是阵列的二维特性,但我不完全明白这会导致减速的原因

或者我的代码中是否存在另一个我看不到的问题

#包括
#包括
#包括
#包括
常数int N=3000;
结构timespec开始、结束;
双**创建_a(){
double*a=(double*)对齐(32,sizeof(double)*N*N);
double**a_index=(double**)aligned_alloc(32,sizeof(double*)*N);

对于(inti=0;i我已经在我的机器上测试了前两个循环,并且我可以重现相同的行为

Time simd reduce measured: 0.000006000 seconds.
time2 (simd reduction): 0.000004000 seconds.
我猜有两个问题:

第一个问题:

多版本的执行时间之间的差异似乎更多地与缓存有关,而不是与矢量化有关。因此,当您使用3000个元素(24 KB)的虚拟数组进行测试时:

通过将第一行矩阵
a
b_t
分别打包为两个新矩阵
a_2
b_2
,即:

for(int i = 0; i < N; i++){
      a_2[0][i]  = a[0][i];
      bt_2[0][i] = b_t[0][i];
 }

// problematic calculation that I can't get to speed up no matter what pragma I use
clock_gettime(CLOCK_REALTIME, &begin);
#pragma omp simd aligned(a_2, bt_2) reduction(+:cell_res)
for (int i = 0; i < N; i++) {
    cell_res += a_2[0][i] * bt_2[0][i];
}
在我看来,您不应该在同一个函数中测试所有这些循环,因为编译器可能会以不同的方式优化这些循环,然后存在缓存这些值等问题。我会在单独的运行中测试它们

现在我的问题是,阻碍SIMD的问题是什么 加速我唯一的猜测是它一定是 数组但我不完全明白这会导致减速的原因

我还通过直接将第一行矩阵
a
b_t
打包到单独的1D数组(而不是矩阵)进行了测试,但结果完全相同。考虑到它的价值。现在您应该在您的环境中进行配置,即测试缓存未命中

更重要的是,测试此版本:

clock_gettime(CLOCK_REALTIME, &begin);
for (int i = 0; i < N; i++) {
    cell_res += a[0][i] * b_t[0][i];
}
clock_gettime(CLOCK_REALTIME, &end);
内存受限,因此使用
SIMD
获得增益的机会较少,不应使用双精度浮点积的
SIMD
。解决方法是将矩阵从双精度变为浮点,从而将必要的内存带宽减少到一半,并将
SIMD
操作的数量增加一倍尽管如此,前面提到的代码片段仍然是内存受限的。尽管如此,您可能会获得一些收益,主要是当值在缓存中时


在我的机器中,从双循环更改为浮动,使
SIMD
版本明显比没有它的版本快,即使不使用包装。这可能也是您遇到的问题。

我已经在我的机器上测试了前两个循环,我可以重现相同的行为

Time simd reduce measured: 0.000006000 seconds.
time2 (simd reduction): 0.000004000 seconds.
我猜有两个问题:

第一个问题:

多版本的执行时间之间的差异似乎更多地与缓存有关,而不是与矢量化有关。因此,当您使用3000个元素(24 KB)的虚拟数组进行测试时:

通过将第一行矩阵
a
b_t
分别打包为两个新矩阵
a_2
b_2
,即:

for(int i = 0; i < N; i++){
      a_2[0][i]  = a[0][i];
      bt_2[0][i] = b_t[0][i];
 }

// problematic calculation that I can't get to speed up no matter what pragma I use
clock_gettime(CLOCK_REALTIME, &begin);
#pragma omp simd aligned(a_2, bt_2) reduction(+:cell_res)
for (int i = 0; i < N; i++) {
    cell_res += a_2[0][i] * bt_2[0][i];
}
在我看来,您不应该在同一个函数中测试所有这些循环,因为编译器可能会以不同的方式优化这些循环,然后存在缓存这些值等问题。我会在单独的运行中测试它们

现在我的问题是,阻碍SIMD的问题是什么 加速我唯一的猜测是它一定是 数组但我不完全明白这会导致减速的原因

我还通过直接将第一行矩阵
a
b_t
打包到单独的1D数组(而不是矩阵)进行了测试,但结果完全相同。考虑到它的价值。现在您应该在您的环境中进行配置,即测试缓存未命中

更重要的是,测试此版本:

clock_gettime(CLOCK_REALTIME, &begin);
for (int i = 0; i < N; i++) {
    cell_res += a[0][i] * b_t[0][i];
}
clock_gettime(CLOCK_REALTIME, &end);
内存受限,因此使用
SIMD
获得增益的机会较少,不应使用双精度浮点积的
SIMD
。解决方法是将矩阵从双精度变为浮点,从而将必要的内存带宽减少到一半,并将
SIMD
操作的数量增加一倍尽管如此,前面提到的代码片段仍然是内存受限的。尽管如此,您可能会获得一些收益,主要是当值在缓存中时

在我的机器中,从double改为float,使得
SIMD
版本明显比没有它的版本快,即使没有使用包装。这也可能是您遇到的问题

clock_gettime(CLOCK_REALTIME, &begin);
for (int i = 0; i < N; i++) {
    cell_res += a[0][i] * b_t[0][i];
}
clock_gettime(CLOCK_REALTIME, &end);
for (int i = 0; i < N; i++) {
        cell_res += a[0][i] * b_t[0][i];
}