该算法已经并行化,即调用对象将工作分成线程.这种计算是在数百万的数组上完成的 – 因此,可能需要一些时间才能完成. 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.所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)