首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于顺序内存访问的编译器嵌套循环优化。

用于顺序内存访问的编译器嵌套循环优化。
EN

Stack Overflow用户
提问于 2012-02-28 05:38:06
回答 2查看 1.2K关注 0票数 5

在矩阵乘基准测试(来自matrix_mult套件的Metis中)中,我遇到了一个奇怪的性能问题。对基准测试进行了优化,使数据平铺,使活动工作集为12 L1 (3块32x32个into ),并适合于L1缓存。长话短说,在某些数组输入大小(4096,8192)上,交换内两大循环的性能差异几乎为4倍,而在其他数组输入大小上的性能差异约为30%。问题本质上归结为按顺序访问元素,而不是按步调模式访问元素。我认为,某些数组大小造成了错误的跨步访问,产生了大量的缓存行冲突。当从双向结合L1转变为8路结合L1时,性能差异明显减小.

我的问题是为什么gcc不优化循环顺序来最大化顺序内存访问?

下面是问题的简化版本(请注意,性能时间高度依赖于L1配置。下面显示的数字来自2.3GHzAMD系统与64K L1双向结合编译与-O3)。

代码语言:javascript
复制
N = ARRAY_SIZE // 1024
int* mat_A = (int*)malloc(N*N*sizeof(int));
int* mat_B = (int*)malloc(N*N*sizeof(int));
int* mat_C = (int*)malloc(N*N*sizeof(int));

// Elements of mat_B are accessed in a stride pattern of length N
// This takes 800 msec  
for (int t = 0; t < 1000; t++) 
   for (int a = 0; a < 32; a++) 
      for (int b = 0; b < 32; b++)
         for (int c = 0; c < 32; c++) 
            mat_C[N*a+b] += mat_A[N*a+c] * mat_B[N*c+b];

// Inner two loops are swapped
// Elements are now accessed sequentially in inner loop
// This takes 172 msec  
for (int t = 0; t < 1000; t++) 
   for (int a = 0; a < 32; a++) 
      for (int c = 0; c < 32; c++) 
         for (int b = 0; b < 32; b++)
            mat_C[N*a+b] += mat_A[N*a+c] * mat_B[N*c+b];
EN

回答 2

Stack Overflow用户

发布于 2012-03-10 21:29:38

  1. gcc可能无法证明指针不重叠。如果使用非标准扩展很好,可以尝试使用限制
  2. gcc没有充分利用您的架构来避免为每个处理器重新编译的必要性。为您的系统使用具有适当值的选项-march可能会有所帮助。
票数 1
EN

Stack Overflow用户

发布于 2012-03-10 21:39:36

gcc有很多优化,你想做什么就做什么。

查找-floop-条带-地雷和-触发器块编译器选项。

引用手册中的话:

在循环上执行循环阻塞转换。块条挖掘循环巢中的每个循环,从而使元素循环的存储器访问适合于缓存。可以使用循环块块大小参数来改变条形长度.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9476939

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档