首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >高性能计算中的数组C[]=A[]*B[]

高性能计算中的数组C[]=A[]*B[]
EN

Stack Overflow用户
提问于 2011-06-08 05:00:38
回答 6查看 298关注 0票数 1

我相信在C++中有这样的代码是很平常的

代码语言:javascript
复制
for(size_t i=0;i<ARRAY_SIZE;++i)
    A[i]=B[i]*C[i];

一个普遍主张的交替是:

代码语言:javascript
复制
double* pA=A,pB=B,pC=C;
for(size_t i=0;i<ARRAY_SIZE;++i)
    *pA++=(*pB++)*(*pC++);

我想知道的是,改进这一守则的最佳方法,因为海事组织需要考虑以下几点:

  1. CPU缓存CPU如何填充它们的缓存以获得最佳命中率?
  2. 我想SSE能改善这一点吗?
  3. 另一件事是,如果代码可以并行化,怎么办?例如使用OpenMP。在这种情况下,指针技巧可能不可用。

如有任何建议,将不胜感激!

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-06-08 05:21:14

性能的规则是

  1. 还没
  2. 找一个目标
  3. 测量
  4. 了解有多大的改进是可能的,并证明花时间得到它是值得的。

对于现代处理器来说更是如此。关于你的问题:

  1. 简单的指针映射通常是由编译器完成的,当他们不这样做的时候,他们可能有很好的理由。
  2. 处理器通常已经被优化为对缓存的顺序访问:简单的代码生成通常会提供最佳的性能。
  3. SSE也许可以改进这一点。但如果你的带宽已经很有限的话就不行了。因此,我们回到了度量和确定边界阶段。
  4. 并行化:与SSE相同的东西。如果带宽有限,使用单个处理器的多个核将于事无补。根据内存结构的不同,使用不同的处理器可能会有所帮助。
  5. 手动循环展开(在现已删除的答案中建议)通常是个坏主意。编译器知道如何做到这一点是值得的(例如,如果它可以进行软件流水线),而对于现代的OOO处理器,情况往往并非如此(它增加了指令和跟踪缓存的压力,而OOO的执行、对跳转和注册重命名的猜测将自动带来解压缩和软件流水线的大部分好处)。
票数 4
EN

Stack Overflow用户

发布于 2011-06-08 05:09:07

我的g++ 4.5.2为两个循环生成了完全相同的代码(修复了double *pA=A, *pB=B, *pC=C;中的错误,它是

代码语言:javascript
复制
.L3:
    movapd  B(%rax), %xmm0
    mulpd   C(%rax), %xmm0
    movapd  %xmm0, A(%rax)
    addq    $16, %rax
    cmpq    $80000, %rax
    jne .L3

(我的ARRAY_SIZE是10000)

编译器作者已经知道这些技巧了。不过,OpenMP和其他并发解决方案值得研究。

票数 5
EN

Stack Overflow用户

发布于 2011-06-08 05:14:56

第一种形式正是编译器将识别和优化的结构类型,几乎可以肯定地自动发出SSE指令。

对于这类琐碎的内部循环,缓存效果是不相关的,因为您正在遍历所有内容。如果您有嵌套循环或一系列操作(如g(f(A,B),C),那么您可能会尝试安排多次访问小内存块,以使其更易于缓存。

不要手动展开循环。如果这是一个好主意(它可能不在现代CPU上),那么编译器也会这样做的。

如果循环很大,而且内部的操作非常复杂,以至于您还没有被限制在内存中,那么OpenMP可能会有所帮助。

通常,以自然和直接的方式编写代码,因为这是优化编译器最有可能理解的。

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

https://stackoverflow.com/questions/6274390

复制
相关文章

相似问题

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