如何通过简单循环达到AVX计算吞吐量

博士AP EcE

最近,我正在使用有限差分法研究计算电动力学的数值求解器。

该求解器的实现非常简单,但是要达到现代处理器的理论吞吐量非常困难,因为对加载的数据只有1个数学运算,例如:

    #pragma ivdep
    for(int ii=0;ii<Large_Number;ii++)
    { Z[ii]  = C1*Z[ii] + C2*D[ii];}

Large_Number约为1,000,000,但不大于10,000,000

我尝试手动展开循环并编写AVX代码,但未能使其更快:

int Vec_Size    = 8;
int Unroll_Num  = 6;
int remainder   = Large_Number%(Vec_Size*Unroll_Num);
int iter        = Large_Number/(Vec_Size*Unroll_Num);
int addr_incr   = Vec_Size*Unroll_Num;

__m256 AVX_Div1, AVX_Div2, AVX_Div3, AVX_Div4, AVX_Div5, AVX_Div6;
__m256 AVX_Z1,   AVX_Z2,   AVX_Z3,   AVX_Z4,   AVX_Z5,   AVX_Z6;

__m256 AVX_Zb = _mm256_set1_ps(Zb);
__m256 AVX_Za = _mm256_set1_ps(Za);
for(int it=0;it<iter;it++)
{
    int addr    = addr + addr_incr;
    AVX_Div1    = _mm256_loadu_ps(&Div1[addr]);     
    AVX_Z1      = _mm256_loadu_ps(&Z[addr]);
    AVX_Z1      = _mm256_add_ps(_mm256_mul_ps(AVX_Zb,AVX_Div1),_mm256_mul_ps(AVX_Za,AVX_Z1));
    _mm256_storeu_ps(&Z[addr],AVX_Z1);

    AVX_Div2    = _mm256_loadu_ps(&Div1[addr+8]);
    AVX_Z2      = _mm256_loadu_ps(&Z[addr+8]);
    AVX_Z2      = _mm256_add_ps(_mm256_mul_ps(AVX_Zb,AVX_Div2),_mm256_mul_ps(AVX_Za,AVX_Z2));
    _mm256_storeu_ps(&Z[addr+8],AVX_Z2);

    AVX_Div3    = _mm256_loadu_ps(&Div1[addr+16]);
    AVX_Z3      = _mm256_loadu_ps(&Z[addr+16]);
    AVX_Z3      = _mm256_add_ps(_mm256_mul_ps(AVX_Zb,AVX_Div3),_mm256_mul_ps(AVX_Za,AVX_Z3));
    _mm256_storeu_ps(&Z[addr+16],AVX_Z3);

    AVX_Div4    = _mm256_loadu_ps(&Div1[addr+24]);
    AVX_Z4      = _mm256_loadu_ps(&Z[addr+24]);
    AVX_Z4      = _mm256_add_ps(_mm256_mul_ps(AVX_Zb,AVX_Div4),_mm256_mul_ps(AVX_Za,AVX_Z4));
    _mm256_storeu_ps(&Z[addr+24],AVX_Z4);

    AVX_Div5    = _mm256_loadu_ps(&Div1[addr+32]);
    AVX_Z5      = _mm256_loadu_ps(&Z[addr+32]);
    AVX_Z5      = _mm256_add_ps(_mm256_mul_ps(AVX_Zb,AVX_Div5),_mm256_mul_ps(AVX_Za,AVX_Z5));
    _mm256_storeu_ps(&Z[addr+32],AVX_Z5);

    AVX_Div6    = _mm256_loadu_ps(&Div1[addr+40]);
    AVX_Z6      = _mm256_loadu_ps(&Z[addr+40]);
    AVX_Z6      = _mm256_add_ps(_mm256_mul_ps(AVX_Zb,AVX_Div6),_mm256_mul_ps(AVX_Za,AVX_Z6));
    _mm256_storeu_ps(&Z[addr+40],AVX_Z6);
}

上面的AVX循环实际上比Inter编译器生成的代码慢一些。

编译器生成的代码可以达到大约8G flops / s,大约是3GHz Ivybridge处理器的单线程理论吞吐量的25%。我想知道是否有可能达到像这样的简单循环的吞吐量。

谢谢!

增加

像您这样的代码的性能改进已经“深入探索”,并且仍然很受欢迎。看一下点积(Z Boson已提供完善的链接)或一些(D)AXPY优化讨论(https://scicomp.stackexchange.com/questions/1932/are-daxpy-dcopy-dscal-overkills

通常,要探索和考虑应用的关键主题是:

  • 由于FMA以及在Haswell上更好的加载/存储端口u架构,AVX2优于AVX
  • 预取。某些平台的“流媒体商店”,“非临时商店”。
  • 线程并行化以达到最大持续带宽
  • 展开(已由您完成;英特尔编译器也可以通过#pragma展开(X)进行此操作)。“流”代码没有太大区别。
  • 最后确定要优化代码的一组硬件平台

最后一个项目符号特别重要,因为对于“流”和整体内存绑定代码而言,了解更多有关目标内存系统的知识很重要。例如,使用现有的,尤其是将来的高端HPC服务器(第二代Xeon Phi,代号为Knights Landing的示例),带宽和计算之间的“屋顶模型”平衡可能会非常不同,甚至与针对以下情况进行优化时所采用的技术也有所不同一般的台式机。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何基于Wireshark计算吞吐量

来自分类Dev

如何使 jmeter 达到目标吞吐量或尝试失败?

来自分类Dev

如何在Linux中计算特定接口的吞吐量?

来自分类Dev

使用 JMeter 从站时如何计算吞吐量?

来自分类Dev

计算链接吞吐量的正确方法

来自分类Dev

计算吞吐量(请求/秒)并绘制

来自分类Dev

如何使用SELECT查看吞吐量?

来自分类Dev

如何增加 WebFlux WebClient 的吞吐量?

来自分类Dev

TCP的吞吐量

来自分类Dev

如何在hadoop集群上根据TestDFSIO基准计算吞吐量

来自分类Dev

如何通过并行化数据库访问来提高吞吐量?

来自分类Dev

是否可以计算CPU的理论I / O吞吐量?

来自分类Dev

总线吞吐量和CPU吞吐量之间的差异及其对顺序和并行计算的影响

来自分类Dev

如何在这个基于Java的简单TCP服务器应用程序中提高吞吐量?

来自分类Dev

如何在这个简单的基于Java的TCP服务器应用程序中提高吞吐量?

来自分类Dev

防火墙吞吐量与UTM吞吐量

来自分类Dev

SIMD延迟吞吐量

来自分类Dev

Jmeter偏差与吞吐量

来自分类Dev

评估内存吞吐量

来自分类Dev

NodeJS数据吞吐量

来自分类Dev

蓝牙SPP吞吐量

来自分类Dev

低估 DynamoDb 吞吐量

来自分类Dev

链接速度与吞吐量

来自分类Dev

如何自动扩展Amazon DynamoDB吞吐量?

来自分类Dev

Redis如何实现高吞吐量和性能?

来自分类Dev

如何提高Parallel.ForEach的吞吐量

来自分类Dev

低延迟如何不能=高吞吐量?

来自分类Dev

如何控制UDP套接字的吞吐量?

来自分类Dev

Redis如何实现高吞吐量和性能?