矢量化代码中随机减速的原因

Posted

技术标签:

【中文标题】矢量化代码中随机减速的原因【英文标题】:Reason for random slowdown in vectorized code 【发布时间】:2017-02-01 05:01:39 【问题描述】:

我在一个项目中使用 AVX2、AVX 和 SSE 编译器内在函数编写了一个特定函数。我知道当 CPU 在 AVX/AVX2 和 SSE 模式之间更改状态时会受到惩罚,因此我在 Visual Studio 项目设置中将增强指令集设置为 AVX2。

在我的代码中,我在 for 循环中反复使用了一些数据。我的代码结构大致如下所示:

//I gather the data that I am going to access again and again and put them 

//into variables so that I use minimal array indexing


__m256 a = (code to get a) 

__m256 b = (code to get b)

.........

for(int i =0; i < large number; i++)


    c = arrayofc[i];

    //operate with a and b and other variables gathered outside the loop.

    d+= result of operations;

 

我面临的问题是,这个函数执行得非常好,但是在程序的某些运行中它会减慢 10 到 15 倍,而同一程序中的其他函数最多会减慢 2 倍.

我使用加速计时器来测量性能、Visual Studio 性能分析器和 GPU 视图。所有这些都表明在我的程序的某些运行中,这个函数执行得非常慢。我的程序没有给出随机结果;每次它给出相同的结果。

GPUview 也没有显示任何其他线程干扰此功能。

曾经我以为我缓存了我的变量,并且在循环内部它只是浮点矢量化操作,打开的 Intel Speed Step 减慢了这个函数,特别是因为这个函数可能比 CPU 更依赖其他可能更依赖内存的功能。但是我的猜测结果是错误的,因为我在禁用 Intel Speed Step 的情况下进行了测试,但仍然遇到了同样的问题。

我也使用软件预取来缓存我在循环外收集的变量,但没有任何好处。

我仍然不确定这是否是由虚拟化引起的。我正在使用的计算机的任务管理器显示 CPU 利用率非常低(1-5%)。内存利用率约为 40%,有时磁盘利用率约为 100%

我们将不胜感激有关此问题的任何帮助。

【问题讨论】:

如果没有某种minimal reproducible example,我认为任何人都无法提供太多帮助。 可能是线程迁移、CPU 热节流、后台驱逐缓存上运行的其他进程(以及其他我想不到的原因)的结果... 任何奇怪的值,例如非正规值? 【参考方案1】:

@Paul R 抱歉这个问题有点含糊。

@Rotem 我认为原因是缓存被驱逐。

@Harold 它与非正规化无关,因为每次我得到相同的结果,如果它受到非正规化的影响,它每次都会影响进程。

我可能找到了问题的答案,但我现在无法验证。我会尽快发布测试结果。

我在函数中所做的是,为了减少数组索引并最大限度地使用寄存器,我将数组中的一些数据放入变量中。

比如我要访问 Darray[0], Darray[1] ...... Darray[6];

在循环开始时我使用了代码

__m256 D0 = 数组[0]; __m256 D1 = 数组[1];

等等。大多数情况下,编译器生成汇编代码,其中变量被放入寄存器并使用寄存器,但在这种情况下,寄存器压力太高,它们没有被放入寄存器,而是被放入不同的内存位置。我打印出 D0 的地址以及与其他变量 D1 、 D2 .... 等的地址差异

这是我得到的结果(第一个数字是 D0 的地址,接下来是它的偏移量):

280449315232 -704 -768 -640 -736 -608

尽管我按顺序访​​问代码中的变量,但有时它们相距甚远。

这是另一个数组的结果(这个最令人惊讶)

280449314144 416 512

另一个:

812970176 128 192 256 224 160 1152

因此,当我访问一个变量时,我不太可能将另一个变量放入缓存中。但是通过循环的一次迭代,我可能会将所有变量都放入缓存中,但是其他一些程序可以随时将它们从缓存中删除。如果我使用数组,即使我提取到缓存中的变量可以从缓存中删除,当我访问其他元素时,我最终也会将一些元素带到缓存中。

我将再次对大部分数据使用数组,并尝试将其余数据放入寄存器中。我将在这篇文章中进行基准测试并报告我的发现。

谢谢。

【讨论】:

很公平,我只是想您可能正在测试每次都更改的随机值或类似的东西。

以上是关于矢量化代码中随机减速的原因的主要内容,如果未能解决你的问题,请参考以下文章

Miller-Rabin随机判素数算法

c ++矢量随机洗牌部分

Js 代码中,ajax请求地址后加随机数防止浏览器缓存的原因

自动矢量化随机播放指令

具有特定比例的二进制随机数组?

用于矢量化的随机读取上的结构阵列 (AoS) 与阵列结构 (SoA)