我的程序包含一个for()循环,它逐行处理一些原始图像数据,我想用OpenMP进行并行化,如下所示:
...
#if defined(_OPENMP)
int const threads = 8;
omp_set_num_threads( threads );
omp_set_dynamic( threads );
#endif
int line = 0;
#pragma omp parallel private( line )
{
// tell the compiler to parallelize the next for() loop using static
// scheduling (i.e. balance workload evenly among threads),
// while letting each thread process exactly one line in a single run
#pragma omp for schedule( static, 1 )
for( line = 0 ; line < max; ++line ) {
// some processing-heavy code in need of a buffer
}
} // end of parallel section
....
问题是:
是否可以使用标准OpenMP pragma / function 为执行我的循环的团队的每个线程提供一个单独的(预分配的)缓冲区(指针)(从而无需分配新的缓冲区每个循环)?
提前致谢。
比约恩
答案 0 :(得分:2)
我可能理解你错了,但我认为应该这样做:
#pragma omp parallel
{
unsigned char buffer[1024]; // private
// while letting each thread process exactly one line in a single run
#pragma omp for // ... etc
for(int line = 0; line < max; ++line ) {
//...
}
}
如果你真的想要为不同的parallell块共享相同的缓冲区,你将不得不求助于线程本地存储。 (Boost和C ++ 11都有比让直接使用TlsAlloc和朋友更容易做(更便携)的设施。
注意这种方法取代了程序员的一些线程安全检查负担,因为完全可以让不同的omp parallel
部分同时运行,特别是当它们运行时正在嵌套。
考虑到并行块可以在运行时嵌套,即使它们不是词法嵌套的。在实践中,这通常不是好的风格 - 并且经常导致糟糕的表现。但是,在执行此操作时,您需要注意这一点。)
答案 1 :(得分:2)
有threadprivate
:http://msdn.microsoft.com/en-us/library/2z1788dd
static int buffer[BUFSIZE];
#pragma omp threadprivate(buffer)
此pragma适用于全局/静态变量,因此您无需担心堆栈溢出。 (在这种堆栈溢出的情况下,通过调整链接器选项来增加堆栈大小并不是一个坏主意。)
请注意,编译器可能具有threadprivate
的不同实现细节。例如,如果变量具有构造函数,则VS 2010编译器无法进行threadprivate。但是,英特尔C / C ++编译器非常有效。
使用单独的omp parallel
和omp for
也是个好主意,因为它显示了它。但是,使用threadprivate
可以直接使用omp parallel for
。
仅供参考:即使您需要分配自己的线程本地存储,在许多情况下,您实际上并不需要调用特定于操作系统的函数调用,例如TlsAlloc
。您可以简单地分配N个数据结构的数组。然后,使用omp_get_thread_num
访问它们,该{{1}}提供从0到N-1的线程ID。当然,您必须通过插入填充来考虑错误共享,以确保每个数据结构应与不同的缓存行对齐(主要是现代CPU缓存具有64字节缓存行)。