我正在使用OpenMP和C实现Boyer-Moore算法。我正在使用gcc编译器。我的串行代码工作正常,但在使用OpenMP进行并行化时,我使用了
#pragma omp parallel for
但我得到的输出不正确。我为不同的运行获取不同的关键字计数,并且关键字的偏移量也不正确。
这个#pragma omp parallel for
指令有什么特殊规则吗?
这是for循环的代码:
#pragma omp parallel
{
#pragma omp for
for(k=0;k<=s.st_size;k+=chunksize-plen)
{
fseek(fp,k,SEEK_SET);
fread(data, chunksize, sizeof(unsigned char), fp);
data[chunksize]='\0';
boyermoore(data,pattern,k,&c);
}
}
答案 0 :(得分:1)
这些语句不能安全地并行化(是一个单词?):
fseek(fp,k,SEEK_SET);
fread(data, chunksize, sizeof(unsigned char), fp);
一个线程与另一个线程同时设置位置或者在另一个线程中读取之前,将会造成严重破坏。更不用说每个线程都会读入相同的data
缓冲区。
答案 1 :(得分:0)
首先,您需要最小化并行区域内共享的数据量。对于这段代码,我认为你需要将data
设为私有,如果它是一个内存缓冲区,请确保每个线程都是独立的:
#pragma omp parallel private(data)
{
data = malloc( chunksize ); /* or whatever size it should be */
#pragma omp for
{ /* ... */ }
free(data);
}
或者,您可以在并行区域之前一次为所有线程分配缓冲区,并使用omp_get_thread_num
找出应该使用缓冲区的哪个部分:
buffer = malloc ( chunksize * omp_get_max_threads() );
#pragma omp parallel private(data)
{
data = (char*)buffer + omp_get_thread_num()*chunksize;
/* ... */
}
也许pattern
和c
也应该是私密的;没有看到boyermoore
函数的代码就很难说。
其次,您需要同步对任何共享变量的访问(除非这些变量仅用于读取)。特别是,任何具有文件的操作都应该是同步的,例如,在#pragma omp critical
的帮助下:
#pragma omp critical
{
fseek(fp,k,SEEK_SET);
fread(data, chunksize, sizeof(unsigned char), fp);
}
第三,您需要确保boyermoore
函数及其调用的任何函数都是线程安全的,并且可以在没有数据争用的情况下同时执行。通常,需要同步对共享状态(例如全局变量)的任何访问。此外,如果任何指针传递给函数(例如&c
似乎是可疑的),您需要确保每个线程中的那些指向不同内存或者同步内存的修改。