OpenMP编程的数据竞争问题
2011-06-01 13:51
169 查看
OpenMP编程的数据竞争问题
使用OpenMP编程时,通常都是将函数内的某段代码并行化执行,但是,对于在函数内声明的变量,很容易被多个线程同时读写访问,这将导致数据竞争问题。
不妨先看一个代码例子:
找出下面代码中的问题
template <class T>
void Parallel_Matrix_Sub(T *a, int row_a, int col_a, int as, T *b, int bs, T *c, int cs)
{
int i, j;
int nCore = omp_get_num_procs();
#pragma omp parallel for num_threads(nCore)
for ( i = 0; i < row_a; i++ )
{
int row_i_a = i * as;
int row_i_b = i * bs;
int row_i_c = i * cs;
for ( j = 0; j < col_a; j++ )
{
//c[i][j] = a[i][j] - b[i][j]
c[row_i_c + j] = a[row_i_a + j] - b[row_i_b + j];
}
}
}
稍有经验的人就可以发现,上面代码中,j变量声明在OpenMP语句块的外面,因此,对各个线程来说,它是共享变量,OpenMP创建的多个线程都会访问j。内层循环中的j++可能会被多个线程同时执行,将导致程序运行出现无法预测的错误。改正后的代码如下:
template <class T>
void Parallel_Matrix_Sub(T *a, int row_a, int col_a, int as, T *b, int bs, T *c, int cs)
{
int i;
const int nCore = omp_get_num_procs();
#pragma omp parallel for num_threads(nCore)
for ( i = 0; i < row_a; i++ )
{
int j;
int row_i_a = i * as;
int row_i_b = i * bs;
int row_i_c = i * cs;
for ( j = 0; j < col_a; j++ )
{
//c[i][j] = a[i][j] - b[i][j]
c[row_i_c + j] = a[row_i_a + j] - b[row_i_b + j];
}
}
}
注意上面的代码中的加粗两行,变量j改为在内层循环内声明,这样创建线程时,变量j为每个线程的局部变量,不存在数据竞争问题。
对于const int nCore = omp_get_num_procs(); 这行,将变量nCore声明为
const类型后,后面的代码就无法对其进行写操作,可以避免线程内的代码对线程外的变量进行写操作,避免数据竞争问题。
根据上面的实例修改情况,可以归纳出两条避免OpenMP出现数据竞争的建议:
1. 尽量在并行循环内部申明局部变量
2. 对于并行循环外面的变量,尽量使用const类型,以保证在并行循环内不会发生写操作。对于没有使用const的变量,表明需要进行写操作,可以在检视代码时重点检视这些未使用const的变量是否用了锁或原子操作来进行保护。
使用OpenMP编程时,通常都是将函数内的某段代码并行化执行,但是,对于在函数内声明的变量,很容易被多个线程同时读写访问,这将导致数据竞争问题。
不妨先看一个代码例子:
找出下面代码中的问题
template <class T>
void Parallel_Matrix_Sub(T *a, int row_a, int col_a, int as, T *b, int bs, T *c, int cs)
{
int i, j;
int nCore = omp_get_num_procs();
#pragma omp parallel for num_threads(nCore)
for ( i = 0; i < row_a; i++ )
{
int row_i_a = i * as;
int row_i_b = i * bs;
int row_i_c = i * cs;
for ( j = 0; j < col_a; j++ )
{
//c[i][j] = a[i][j] - b[i][j]
c[row_i_c + j] = a[row_i_a + j] - b[row_i_b + j];
}
}
}
稍有经验的人就可以发现,上面代码中,j变量声明在OpenMP语句块的外面,因此,对各个线程来说,它是共享变量,OpenMP创建的多个线程都会访问j。内层循环中的j++可能会被多个线程同时执行,将导致程序运行出现无法预测的错误。改正后的代码如下:
template <class T>
void Parallel_Matrix_Sub(T *a, int row_a, int col_a, int as, T *b, int bs, T *c, int cs)
{
int i;
const int nCore = omp_get_num_procs();
#pragma omp parallel for num_threads(nCore)
for ( i = 0; i < row_a; i++ )
{
int j;
int row_i_a = i * as;
int row_i_b = i * bs;
int row_i_c = i * cs;
for ( j = 0; j < col_a; j++ )
{
//c[i][j] = a[i][j] - b[i][j]
c[row_i_c + j] = a[row_i_a + j] - b[row_i_b + j];
}
}
}
注意上面的代码中的加粗两行,变量j改为在内层循环内声明,这样创建线程时,变量j为每个线程的局部变量,不存在数据竞争问题。
对于const int nCore = omp_get_num_procs(); 这行,将变量nCore声明为
const类型后,后面的代码就无法对其进行写操作,可以避免线程内的代码对线程外的变量进行写操作,避免数据竞争问题。
根据上面的实例修改情况,可以归纳出两条避免OpenMP出现数据竞争的建议:
1. 尽量在并行循环内部申明局部变量
2. 对于并行循环外面的变量,尽量使用const类型,以保证在并行循环内不会发生写操作。对于没有使用const的变量,表明需要进行写操作,可以在检视代码时重点检视这些未使用const的变量是否用了锁或原子操作来进行保护。
相关文章推荐
- OpenMP编程的数据竞争问题
- .NET 并行(多核)编程系列之七 共享数据问题和解决概述
- C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性
- windows socket编程中send与recv函数的收发数据不一致问题
- C++多线程编程学习一 [关于数据竞争问题]
- 大数据面试编程问题
- 读取文件数据的编程出现的问题
- 我的学习笔记(C#编程中将截断或二进制数据的问题)
- 有关C语言的数据统计和编程问题 高手请进
- .NET 并行(多核)编程系列之七 共享数据问题和解决概述
- 关于BF53X的c编程数据类型问题
- 网络编程:流式套接字应用数据完整包读取问题
- Linux下串口编程遇 接收数据错误问题及原因
- OpenMP编程->数据传递
- .NET 4并行编程之共享数据问题和解决概述
- OpenMP编程->数据传递
- 多线程数据竞争问题
- IOS网络编程发送数据的问题
- .NET 并行(多核)编程系列之七 共享数据问题和解决概述
- C#串口编程问题:一个测试数据怎么拆分成2个字符串,做了2次发送?