运行时不可分割的循环大小对openMP SIMD的影响

问题描述 投票:0回答:1

在阅读了几篇不同的文章而没有找到答案后,我将介绍问题,然后提出问题。

我有一段代码可以简化为一系列循环,如下所示。

#pragma omp parallel for simd
for(int i = 0; i < a*b*c; i++)
{
    array1[i] += array2[i] * array3[i];
}

现在,我遇到的大多数SIMD使用示例都在编译时修复了a,b和c,允许进行优化。但是,我的代码要求在运行时确定b和c的值。

让我们说,对于我使用的计算机的情况,寄存器可以容纳4个值,并且abc的值是127.我对编译时间的理解是编译器将向量化所有可被4整除的东西,然后序列化其余部分(如果我错了,请更正)。但是,这是编译器完全了解问题的时候。如果我现在允许运行时选择a,b和c并且值为127,那么矢量化将如何进行?天真的我会假设幕后的代码足够聪明,可以理解这可能会发生串行和矢量代码,并且调用最合适。但是,由于这是一个假设,我希望有更多有关该主题的知识可以进一步启发我,因为我不希望由于误解而意外溢出或不处理数据。

关于这个问题很重要,我使用OpenMP 4.0和C gcc编译器,虽然我希望这不会改变你的答案,因为我总是会尝试使用最新的OpenMP版本,不幸的是可能需要定期更改编译器。

c openmp simd
1个回答
0
投票

通常,编译器将展开超出simd长度。为了获得最佳效果,特别是使用gcc,您可以指定此展开因子,例如--param max-unroll-times = 2(如果你不期望更长的循环)。如果simd长度为4,则循环将一次消耗8次迭代,剩下一个。 gcc会构建一个余数循环,有点像Duff的设备,它可能有15次迭代,并计算在运行时跳转的位置。英特尔编译器以不同的方式处理向量化的余数循环。假设您有2个可用的simd宽度,则余数循环将使用较短的宽度而不展开,因此串行部分尽可能短。在编译未对齐数据的一般情况时,两端都有一个余数循环,开头的循环限制为对齐存储值所需的长度。随着omp parallel simd的组合,情况变得更加复杂;通常情况下,循环块的大小必须不同,有人可能认为内部块可能已设置为对齐,末端块较小(通常不完成)。

© www.soinside.com 2019 - 2024. All rights reserved.