gpt4 book ai didi

c - 矩阵乘法的 OpenMP 性能问题

转载 作者:太空宇宙 更新时间:2023-11-04 01:55:28 25 4
gpt4 key购买 nike

我在使用 OpenMp 时遇到性能问题。我正在尝试测试不使用 OpenMP 的单线程程序和使用 OpenMP 的应用程序的结果。通过在线查看比较矩阵链乘法程序的结果,openMP 实现的速度是其 2 到 3 倍,但我的两个应用程序的实现速度相同。我实现 openMP 的方式不正确吗?关于 openMP 的任何指示以及如何正确实现它?任何帮助深表感谢。提前致谢。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main( int argc , char *argv[] )
{
srand(time(0));
if ( argc != 2 )
{
printf("Usage: %s <size of nxn matrices>\n", argv[0]);
return 1;
}

int n = atoi( argv[1] );
int a, b;
double A[n][n], B[n][n], C[n][n];
FILE *fp;
fp = fopen("/home/mkj0002/CPE631/Homework2/ArrayTry/matrixResults", "w+"); //For the LeCASA machine

for(a = 0; a < n; a++)
{
for(b = 0; b < n; b++)
{
A[a][b] = ((double)rand()/(double)RAND_MAX); //Number between 0 and 1
A[a][b] = (double)rand(); //Number between 0 and RAND_MAX
B[a][b] = ((double)rand()/(double)RAND_MAX); //Number between 0 and 1
B[a][b] = (double)rand(); //Number between 0 and RAND_MAX
C[a][b] = 0.0;
}
}

#pragma omp parallel shared(A,B,C)
{
int i,j,k;
#pragma omp for schedule(guided,n)
for(i = 0; i < n; ++i)
{
for(j = 0; j < n; ++j)
{
double sum = 0;
for(k = 0; k < n; ++k)
{
sum += A[i][k] * B[k][j];
}

C[i][j] = sum;
fprintf(fp,"0.4lf",C[i][j]);
}
}
}

if(fp)
{
fclose(fp);
}
fp = NULL;

return 0;
}

最佳答案

(1) 不要在并行区域内执行 I/O。当您将其移出并将许多 C 变量同时写入文件时,您会看到瞬间加速。

(2) 完成上述操作后,您应该将调度更改为 static,因为每个循环将执行完全相同的计算量,并且不再需要招致花式调度的开销。

(3) 此外,为了更好地利用缓存,您应该交换jk 循环。要看到这一点,想象一下在当前循环中只访问 B 变量。

for(j = 0; j < n; ++j)
{
for(k = 0; k < n; ++k)
{
B[k][j] += 5.0;
}
}

您可以看到它是如何访问 B 的,就好像它是以 Fortran 的列优先格式存储的一样。可以找到更多信息 here .更好的选择是:

for(k = 0; k < n; ++k)
{
for(j = 0; j < n; ++j)
{
B[k][j] += 5.0;
}
}

回到您的示例,我们仍然需要处理 sum 变量。一个简单的建议是存储您正在计算的当前 sum 行,然后在完成当前循环后将它们全部保存。

结合所有 3 个步骤,我们得到如下结果:

#pragma omp parallel shared(A,B,C)
{
int i,j,k;
double sum[n]; // one for each j

#pragma omp for schedule(static)
for(i = 0; i < n; ++i)
{
for(j = 0; j < n; ++j)
sum[j] = 0;

for(k = 0; k < n; ++k)
{
for(j = 0; j < n; ++j)
{
sum[j] += A[i][k] * B[k][j];
}
}

for(j = 0; j < n; ++j)
C[i][j] = sum[j];
}
}

// perform I/O here using contiguous blocks of C variable

希望对您有所帮助。

编辑:根据@Zboson 的建议,完全删除 sum[j] 并将其替换为 C[i][ 会更容易j] 贯穿整个程序。

关于c - 矩阵乘法的 OpenMP 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34984453/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com