我刚刚开始使用OpenMP并且正在编写一个函数,它将数组划分为numBlocks
块并通过检查{{1来计算每个块上的直方图(即每个块一个直方图)每个块的元素(在代码I' m提供中,直方图通过整数blockSize
到1
记录块中元素的可分性。
在第一个numBuckets
循环中,我使用以下命令为每个块创建一个线程:
omp for
以另一种方式实现它,我请求每个线程对#pragma omp for schedule(static)
for(uint blockNum = 0; blockNum < numBlocks; blockNum++){
for(uint blockSubIdx = 0; blockSubIdx < blockSize; blockSubIdx++){
uint idx = blockNum * blockSize + blockSubIdx;
// Compute histogram here by examining array[idx]
}
}
个元素进行操作,我之前断言blockSize
:
array.size() == numBlocks * blockSize
如果我增加线程数(使用#pragma omp for schedule(static, blockSize)
for(uint idx = 0; idx < array.size(); idx++){
uint blockNum = idx / blockSize;
// Compute histogram here by examining array[idx]
}
)高于某个阈值(我的计算节点上为78),则第二种方法无法正常工作 - 结果直方图值与串行计算值不匹配。
根据https://computing.llnl.gov/tutorials/openMP/,看起来第二种方法中的大小export OMP_NUM_THREADS
的块是连续的,所以我不清楚它为什么会失败。但是,似乎多个线程正在写入直方图中的相同索引。我有什么微妙之处吗?
以下是整个源代码的要点:https://gist.github.com/anonymous/5391777。
更新:线程阈值确实显示对blockSize
的某些依赖性。它不是我试图理解的阈值的特定值,而是阈值的存在。
答案 0 :(得分:2)
在我看来,你正试图融合循环。你可以试试这个。我不知道这是否能回答你的问题。
#pragma omp parallel for schedule(static)
for(uint n = 0; n < (numBlocks*blockSize); n++){
uint blockNum = n/blockSize;
uint blockSubIdx = n%blockSize;
uint idx = blockNum * blockSize + blockSubIdx;
// Compute histogram here by examining array[idx]
}
另外,为什么要尝试增加线程数?您的CPU一次只能运行一定数量的硬件线程。增加OpenMP的线程数我认为不会有助于提高性能。为什么不将它们保留为默认值?
最后,如果根据idx计算直方图需要不同的时间,您可能需要尝试使用schedule(dynamic)
。