我基本上有三个关于OpenMp的问题。
Q1。 OpenMp是否为共享变量提供互斥?考虑以下带有三个嵌套循环的简单矩阵乘法代码,使用C ++中的OpenMp进行并行化。这里A,B和C是动态空间分配的双**类变量。线程计数适当地赋值。
#pragma omp parallel
{
int tid = omp_get_thread_num();
int fraction = (n/threadCount);
int start = tid * fraction;
int end = (tid+1) * fraction;
for (int start = 0; i < end; i++)
{
for (int j = 0; j < N; j++)
{
C[i][j] = 0;
for (int k = 0; k < N; k++)
C[i][j] += A[i][k] * B[k][j];
}
}
}
这里的事情是,从A和B读取并写入C的互斥是不必要的。但是,如果由于A,B和C上的互斥导致额外开销,则有利于缓解互斥锁的A,B和C.如何实现?
Q2。 考虑将两个私有变量tempA和tempB引入上面的代码中,如下所示。
double **tempA, **tempB;
#pragma omp parallel private(tempA, tempB)
{
int tid = omp_get_thread_num();
int fraction = (n/threadCount);
int start = tid * fraction;
int end = (tid+1) * fraction;
tempA = A;
tempB = B;
for (int start = 0; i < end; i++)
{
for (int j = 0; j < N; j++)
{
C[i][j] = 0;
for (int k = 0; k < N; k++)
C[i][j] += tempA[i][k] * tempB[k][j];
}
}
}
这种策略会在计算中减轻A和B的互斥吗?我的意思是,虽然所有线程都访问相同的位置(由A和tempA,B和tempB引用),但它们通过不同的局部变量引用它们。
Q3。 另外,我想知道在并行代码段中声明变量tempA和tempB的区别,而不是在外部声明它们。当然,我们在指令中不需要私人条款。还有其他重大差异。
答案 0 :(得分:2)
默认情况下,不提供同步机制。但OpenMP提供了明确使用此类机制的可能性。出于此目的,请使用#pragma omp atomic
,#pragma omp atomic read
,#pragma omp atomic write
。使用关键部分的另一个选择:#pragma omp critical
- 更通用和更强大的选项,但并非总是需要。
通过不同的变量访问相同的内存位置不会改变有关并发访问的任何内容。你应该使用原子来提供保证。
如果在pragma omp parallel
内声明变量 - 它们对于一个线程是私有的。有关详细信息,请参阅this和this帖子。
此外,如果您使用的是C ++ 11,则可以使用std::atomic
变量。