OpenMP 嵌套循环竞争条件
OpenMP Nested For Loop Race Condition
我在当前情况下遇到了种族问题。我正在尝试创建线程数量,因为有内核,在 OMP 上使用锁。我尝试过 #pragma omp critical
,其中 #pragma amp atomic
和 none 也在提供帮助。我得到了一些疯狂的负数...我知道如何使用 private 来做到这一点,但我想实际同步线程,而不是为线程创建多个变量然后在最后组合。
// multiplication
#pragma omp parallel for
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
c[i][j] = 0.;
for (k = 0; k < N; k++)
{
omp_set_lock(&lock);
//#pragma omp critical
//#pragma omp atomic
c[i][j] += a[i][k] * b[k][j];
threadTasks[omp_get_thread_num()]++;
omp_unset_lock(&lock);
}
printf("[%d, %d]: Thread ID %d\n", i, j, omp_get_thread_num());
}
}
对于此矩阵乘法,您不需要针对竞争条件的任何保护(锁、原子、临界区)。事实上,这样做会完全破坏你的表现。由于每个线程都在执行不同的 i
,不同的线程永远无法写入或读取 c[i][j]
.
的相同索引
但是,您需要为内部循环设置私有循环变量,否则一切都会出错。通常,尽可能在本地声明所有变量。然后它们是隐式私有的,这对于在私有部分之外不需要的变量几乎总是正确的。
I know how to do it using private, but I want to actually synchronize the threads, not create multiple variables for the threads and then combine at the end.
对于内部循环变量,除了将它们设为私有之外别无选择。很多时候,减少(私有副本,最后聚合)可以比共享结果变量执行得更好。在这种情况下,共享结果应该没问题。
对于包含各种操作的多个嵌套循环,我不会使用#pragma omp parallel for
,而是分解为#pragma omp parallel
和#pragma omp for collapse(2)
。
请参阅下面的完整代码:
#pragma omp parallel
{
#pragma omp for collapse(2)
for (i = 0; i < N; i++){
for (j = 0; j < N; j++){
c_parallel[i][j] = 0.;
for (k = 0; k < N; k++) {
c_parallel[i][j] += a_parallel[i][k] * b_parallel[k][j];
}
}
}
}//end parallel region
我正在使用 vector< vector<float>>
作为矩阵,在 i5 4 cores/Win10 上的性能提高了 300%。
我在当前情况下遇到了种族问题。我正在尝试创建线程数量,因为有内核,在 OMP 上使用锁。我尝试过 #pragma omp critical
,其中 #pragma amp atomic
和 none 也在提供帮助。我得到了一些疯狂的负数...我知道如何使用 private 来做到这一点,但我想实际同步线程,而不是为线程创建多个变量然后在最后组合。
// multiplication
#pragma omp parallel for
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
c[i][j] = 0.;
for (k = 0; k < N; k++)
{
omp_set_lock(&lock);
//#pragma omp critical
//#pragma omp atomic
c[i][j] += a[i][k] * b[k][j];
threadTasks[omp_get_thread_num()]++;
omp_unset_lock(&lock);
}
printf("[%d, %d]: Thread ID %d\n", i, j, omp_get_thread_num());
}
}
对于此矩阵乘法,您不需要针对竞争条件的任何保护(锁、原子、临界区)。事实上,这样做会完全破坏你的表现。由于每个线程都在执行不同的 i
,不同的线程永远无法写入或读取 c[i][j]
.
但是,您需要为内部循环设置私有循环变量,否则一切都会出错。通常,尽可能在本地声明所有变量。然后它们是隐式私有的,这对于在私有部分之外不需要的变量几乎总是正确的。
I know how to do it using private, but I want to actually synchronize the threads, not create multiple variables for the threads and then combine at the end.
对于内部循环变量,除了将它们设为私有之外别无选择。很多时候,减少(私有副本,最后聚合)可以比共享结果变量执行得更好。在这种情况下,共享结果应该没问题。
对于包含各种操作的多个嵌套循环,我不会使用#pragma omp parallel for
,而是分解为#pragma omp parallel
和#pragma omp for collapse(2)
。
请参阅下面的完整代码:
#pragma omp parallel
{
#pragma omp for collapse(2)
for (i = 0; i < N; i++){
for (j = 0; j < N; j++){
c_parallel[i][j] = 0.;
for (k = 0; k < N; k++) {
c_parallel[i][j] += a_parallel[i][k] * b_parallel[k][j];
}
}
}
}//end parallel region
我正在使用 vector< vector<float>>
作为矩阵,在 i5 4 cores/Win10 上的性能提高了 300%。