c/c++语言开发共享为什么_mm_stream_ps会产生L1 / LL缓存未命中?

我正在尝试优化计算密集型算法,并且遇到了一些缓存问题。 我有一个巨大的缓冲区,偶尔写入并随机写入,并在应用程序结束时只读取一次。 显然,写入缓冲区会产生大量的缓存未命中,并且还会污染之后需要再次进行计算的缓存。 我尝试使用非时间移动instrinsics,但缓存未命中(由valgrind报告并由运行时测量支持)仍然会发生。 但是,为了进一步研究非时间动作,我写了一个小测试程序,你可以在下面看到。 顺序访问,大缓冲区,只写。

#include  #include  #include  #include  void tim(const char *name, void (*func)()) { struct timespec t1, t2; clock_gettime(CLOCK_REALTIME, &t1); func(); clock_gettime(CLOCK_REALTIME, &t2); printf("%s : %f s.n", name, (t2.tv_sec - t1.tv_sec) + (float) (t2.tv_nsec - t1.tv_nsec) / 1000000000); } const int CACHE_LINE = 64; const int FACTOR = 1024; float *arr; int length; void func1() { for(int i = 0; i < length; i++) { arr[i] = 5.0f; } } void func2() { for(int i = 0; i < length; i += 4) { arr[i] = 5.0f; arr[i+1] = 5.0f; arr[i+2] = 5.0f; arr[i+3] = 5.0f; } } void func3() { __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f); for(int i = 0; i < length; i += 4) { _mm_stream_ps(&arr[i], buf); } } void func4() { __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f); for(int i = 0; i < length; i += 16) { _mm_stream_ps(&arr[i], buf); _mm_stream_ps(&arr[4], buf); _mm_stream_ps(&arr[8], buf); _mm_stream_ps(&arr[12], buf); } } int main() { length = CACHE_LINE * FACTOR * FACTOR; arr = malloc(length * sizeof(float)); tim("func1", func1); free(arr); arr = malloc(length * sizeof(float)); tim("func2", func2); free(arr); arr = malloc(length * sizeof(float)); tim("func3", func3); free(arr); arr = malloc(length * sizeof(float)); tim("func4", func4); free(arr); return 0; } 

函数1是天真的方法,函数2使用循环展开。 函数3使用movntps,实际上至少在我检查-O0时插入到程序集中。 在函数4中,我尝试一次发出几个movntps指令,以帮助CPU进行写入组合。 我用gcc -g -lrt -std=gnu99 -OX -msse4.1 test.c编译了代码,其中X是[0..3]之一。 结果很有趣,充其量说:

 -O0 func1 : 0.407794 s. func2 : 0.320891 s. func3 : 0.161100 s. func4 : 0.401755 s. -O1 func1 : 0.194339 s. func2 : 0.182536 s. func3 : 0.101712 s. func4 : 0.383367 s. -O2 func1 : 0.108488 s. func2 : 0.088826 s. func3 : 0.101377 s. func4 : 0.384106 s. -O3 func1 : 0.078406 s. func2 : 0.084927 s. func3 : 0.102301 s. func4 : 0.383366 s. 

正如你所看到的,当程序没有被gcc优化时,_mm_stream_ps比其他程序快一点,但是当gcc优化打开时,它的目的明显失败。 Valgrind仍然报告了许多缓存写入未命中。

所以,问题是:为什么即使我使用NTA流指令,仍然会发生那些(L1 + LL)缓存未命中? 为什么特别是func4这么慢?! 有人可以解释/推测这里发生了什么吗?

    不应该func4是这样的:

    需要了解更多c/c++开发分享为什么_mm_stream_ps会产生L1 / LL缓存未命中?,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!

     void func4() { __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f); for(int i = 0; i < length; i += 16) { _mm_stream_ps(&arr[i], buf); _mm_stream_ps(&arr[i+4], buf); _mm_stream_ps(&arr[i+8], buf); _mm_stream_ps(&arr[i+12], buf); } } 

      以上就是c/c++开发分享为什么_mm_stream_ps会产生L1 / LL缓存未命中?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/980409.html

      (0)
      上一篇 2021年12月13日
      下一篇 2021年12月13日

      精彩推荐