我无法弄清楚为什么这个功能的性能如此糟糕。我有一个核心2 Duo机器,我知道它只创造2个trheads所以它不是一个太多线程的问题。我希望结果更接近我的pthread结果。
这些是我的编译标志(故意不做任何优化标志) gcc -fopenmp -lpthread -std = c99 matrixMul.c -o matrixMul
这些是我的结果
Sequential matrix multiply: 2.344972
Pthread matrix multiply: 1.390983
OpenMP matrix multiply: 2.655910
CUDA matrix multiply: 0.055871
Pthread Test PASSED
OpenMP Test PASSED
CUDA Test PASSED
void openMPMultiply(Matrix* a, Matrix* b, Matrix* p)
{
//int i,j,k;
memset(*p, 0, sizeof(Matrix));
int tid, nthreads, i, j, k, chunk;
#pragma omp parallel shared(a,b,p,nthreads,chunk) private(tid,i,j,k)
{
tid = omp_get_thread_num();
if (tid == 0)
{
nthreads = omp_get_num_threads();
}
chunk = 20;
// #pragma omp parallel for private(i, j, k)
#pragma omp for schedule (static, chunk)
for(i = 0; i < HEIGHT; i++)
{
//printf("Thread=%d did row=%d\n",tid,i);
for(j = 0; j < WIDTH; j++)
{
//#pragma omp parallel for
for(k = 0; k < KHEIGHT ; k++)
(*p)[i][j] += (*a)[i][k] * (*b)[k][j];
}
}
}
}
感谢您的帮助。
答案 0 :(得分:2)
由于矩阵乘法是一个令人尴尬的并行,它的加速应该在双核上接近2。由于减少了高速缓存未命中,矩阵乘法甚至通常显示超线性加速(在双核上大于2)。通过查看代码我没有看到明显的错误,但是出了点问题。以下是我的建议:
只需仔细检查工作线程数。在您的情况下,应创建2个线程。或者,尝试通过调用omp_set_num_threads
进行设置。另外,看看是否充分利用了2个内核(即Windows上100%的CPU利用率,Linux上的200%)。
删除不必要的nthreads
和chunk
以清理代码。这些可以在平行部分之外制备。但即便如此,也不应该损害加速。
矩阵是正方形(即HEIGHT == WIDTH == KHEIGHT)?如果它不是方阵,则可能存在工作负载不平衡,这可能会损害加速。但是,考虑到pthread的加速(大约1.6,这对我来说也很奇怪),我认为工作量不平衡太多了。
尝试使用默认的静态计划:不要指定chunk
,只需写#pragma omp for
。
我最好的猜测是Matrix
的结构可能会有问题。 Matrix
究竟是什么样的?在最坏的情况下,虚假共享可能会严重影响性能。但是,在这种简单的矩阵乘法中,虚假共享应该不是一个大问题。 (如果你不知道细节,我可以解释更多细节)。
虽然您已注释掉,但请勿将#pragma omp parallel for
放在for-k
,这会导致嵌套并行循环。在矩阵乘法中,由于最外层的循环是可并行化的,所以绝对是浪费。
最后,尝试运行以下非常简单的OpenMP矩阵乘法代码,并查看加速:
double A[N][N], B[N][N], C[N][N];
#pragma omp parallel for
for (int row = 0; row < N; ++row)
for (int col = 0; col < N; ++col)
for (int k = 0; k < N; ++k)
C[row][col] += A[row][k]*B[k][col];