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

时间:2017-02-01 05:01:39

标签: c performance sse avx avx2

我在一个使用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更依赖于其他功能可能更依赖于内存。但我的猜测结果是错误的,因为我测试了英特尔Speed Speed禁用并仍然有同样的问题。

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

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

非常感谢有关此问题的任何帮助。

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

例如我想访问Darray [0],Darray [1] ...... Darray [6];

在looop的开头,我使用了代码

__ m256 D0 = Darray [0];   __m256 D1 = Darray [1];

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

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

280449315232 -704 -768 -640 -736 -608

即使我按顺序访​​问代码中的变量,有时它们相距很远。

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

280449314144 416 512

另一个:

812970176 128 192 256 224 160 1152

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

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

谢谢。