通过标量有效地乘以大复数向量C.

通过标量有效地乘以大复数向量C.,第1张

概述我目前正在尝试最有效地执行复数数组的就地乘法(内存以与std :: complex相同的方式对齐,但目前使用我们自己的ADT)由一组标量值相同size作为复数数组. 该算法已经并行化,即调用对象将工作分成线程.这种计算是在数百万的数组上完成的 – 因此,可能需要一些时间才能完成. CUDA不是这个产品的解决方案,尽管我希望如此.我确实可以获得提升,因此有一些使用BLAS / uBLAS的潜力. 然 我目前正在尝试最有效地执行复数数组的就地乘法(内存以与std :: complex相同的方式对齐,但目前使用我们自己的ADT)由一组标量值相同size作为复数数组.

该算法已经并行化,即调用对象将工作分成线程.这种计算是在数百万的数组上完成的 – 因此,可能需要一些时间才能完成. CUDA不是这个产品的解决方案,尽管我希望如此.我确实可以获得提升,因此有一些使用BLAS / uBLAS的潜力.

然而,我想,SIMD可能会产生更好的结果,但我对如何使用复杂的数字做得不够熟悉.我现在的代码如下(请记住,这会被分成线程,这些线程对应于目标机器上的核心数).目标机器也是未知的.因此,通用方法可能是最好的.

voID cmult_scalar_inplace(fcomplex *values,const int start,const int end,const float *scalar){    for (register int IDx = start; IDx < end; ++IDx)    {        values[IDx].real *= scalar[IDx];        values[IDx].imag *= scalar[IDx];    }}

fcomplex的定义如下:

struct fcomplex{    float real;    float imag;};

我已经尝试手动展开循环,因为我的finally循环计数总是2的幂,但编译器已经为我做了这个(我已经展开到32).我已经尝试了对标量的const浮点引用 – 我认为我将保存一个访问权限 – 这证明与编译器已经在做的事情相同.我尝试过STL和转换,哪个游戏结果很接近,但还是更糟.我也试过转换为std :: complex并允许它使用重载运算符来进行乘法的标量*复合,但这最终会产生相同的结果.

那么,任何有想法的人?非常感谢您花时间考虑这个问题!目标平台是windows.我正在使用Visual Studio 2008.产品也不能包含GPL代码!非常感谢.

解决方法 您可以使用SSE轻松完成此 *** 作,例如

voID cmult_scalar_inplace(fcomplex *values,const float *scalar){    for (int IDx = start; IDx < end; IDx += 2)    {        __m128 vc = _mm_load_ps((float *)&values[IDx]);        __m128 vk = _mm_set_ps(scalar[IDx + 1],scalar[IDx + 1],scalar[IDx],scalar[IDx]);        vc = _mm_mul_ps(vc,vk);        _mm_store_ps((float *)&values[IDx],vc);    }}

请注意,值和标量需要16字节对齐.

或者您可以使用英特尔ICC编译器,让它为您完成艰苦的工作.

UPDATE

这是一个改进版本,它将循环展开2倍,并使用单个加载指令获得4个标量值,然后将其解压缩为两个向量

voID cmult_scalar_inplace(fcomplex *values,const float *scalar){    for (int IDx = start; IDx < end; IDx += 4)    {        __m128 vc0 = _mm_load_ps((float *)&values[IDx]);        __m128 vc1 = _mm_load_ps((float *)&values[IDx + 2]);        __m128 vk = _mm_load_ps(&scalar[IDx]);        __m128 vk0 = _mm_shuffle_ps(vk,vk,0x50);        __m128 vk1 = _mm_shuffle_ps(vk,0xfa);        vc0 = _mm_mul_ps(vc0,vk0);        vc1 = _mm_mul_ps(vc1,vk1);        _mm_store_ps((float *)&values[IDx],vc0);        _mm_store_ps((float *)&values[IDx + 2],vc1);    }}
总结

以上是内存溢出为你收集整理的通过标量有效地乘以大复数向量C.全部内容,希望文章能够帮你解决通过标量有效地乘以大复数向量C.所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1230921.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存