我有这种嵌套循环:我想知道如何以最佳形式并行化:
第二个和第三个for
以及第五个和第六个for
同时运行
时间
序列号
for
醇>
如果我有24个核心,并希望在16个线程之间划分外部并使用其余部分来执行内部for
,例如执行第二个for
,8个线程,而不仅仅是一个线程,我该怎么办 ?
void main()
{
//first_for
for(int y=0; y< height; y++)
{
//second_for
for(int x=0; x< width-1; x++)
{
func1();
}
//third_for
for(int x=0; x< width-1; x++)
{
func2();
}
}
//fourth_for
for(int x=0; x<width; x++)
{
//fifth_for
for(int y=0; y< height-1; y++)
{
func3();
}
//sixth_for
for(int y=0; y< height-1; y++)
{
func4();
}
}
}
答案 0 :(得分:0)
关于并行性介绍,通常会说较粗糙的级别更好,所以如果你可以在粗略的级别添加并行指令,那么为什么你还要添加嵌套的并行性呢?
所以基于可以同时运行的内容,我会像这样编写主要内容:
int main()
{
//first_for
#pragma parallel for
for(int y=0; y< height; y++)
{
//second_for and third_for
for(int x=0; x< width-1; x++)
{
func1();
func2();
}
}
//fourth_for
#pragma parallel for
for(int x=0; x<width; x++)
{
//fifth_for and //sixth_for
for(int y=0; y< height-1; y++)
{
func3();
func4();
}
}
return 0;
}
我们通过合并2个内循环来增加每行和每列的工作量
我们添加openMP指令,根据您的核心数量将该计算循环拆分为较小的块。
看看你是否可以反转第一个循环,因为取决于你在里面做什么以及你的“图像”如何在内存中映射,首先处理列可能会导致很多缓存错误....
修改
你可以启用嵌套并行,但是它的方式错误,过多的循环和线程访问不同的内存只会降低性能,你也会有一个专为24核设计的解决方案,可能无法扩展32, 48核心等...但如果你坚持你必须设置一个env变量或调用openMP函数:
call omp_set_nested()
or
set OMP_NESTED=TRUE|FALSE
在顶级循环上添加openMP子句后指定指定所需的chunck大小,以便只有X线程。
int chunckSize = height / X;
#pragma parallel for schedule ( static , chunckSize)
openMP线程团队应该由24个线程组成,但通过这样做,只有X才能完成工作。遵循嵌套循环的逻辑。
但这不是我推荐的解决方案!
答案 1 :(得分:0)
除了已经说过的内容之外,您可能希望明确启用嵌套并行性。可以在运行时使用库调用或使用环境变量(对于OpenMP)来执行此操作。
有关详细信息,请查看此Oracle Docs。