通常,为某个唯一操作定义BLAS子例程。例如,
DAXPY
必须y <-- ax + y
DSCAL
必须x = ax
。
我希望实现的目标是:
z = ax+by
和y = ax
。
如何“扩展”BLAS的子程序,以便我可以执行上述操作? (这些操作不一定相互关联)
我试过了:
声明一个假人,然后DCOPY
将假人移动到所需的向量。比如,DCOPY(dummy,x); DSCAL(a,dummy),DCOPY(y,dummy)
创建我自己的OpenMP实现
使用DCOPY(y,a*x)
等技巧获取y = ax
但问题是,这些方法似乎都没有给我一个确定的答案,因为这是解决这个问题的最佳方法。我知道我应该“配置文件,配置文件,配置文件”,而不是问我,但我已经尝试了所有这些,但每次我改变矢量一点,早期最好的方法突然变得最差,反之亦然。
此外,
答案 0 :(得分:2)
首先,在您对y&lt; - a x的解释中,您可以使用DCOPY(y,x)删除一次过多的复制; DSCAL(A,Y)。
其次,OpenMP恕我直言不是这类问题的解决方案,因为它们是“内存限制”。惩罚在于通过计算和向量化来管理存储器访问,其通过使用向量存储器访问来使用更多带宽。由于(分支预测,缓存策略,寄存器文件配置等),手动调整的代码应该非常复杂。您需要像R. Clint Whaley的Atlas库那样自动生成特定平台的优化操作实现。 AFAIK,有BLAST标准(2001),也许你会发现你提出的操作的类似变体。您可能需要通过电子邮件将这些操作添加到自动调整器中。
作为一个起点,我建议你使用z = ax + by的以下实现。 在这种情况下,无论如何都会写z,如果x和y是只读的,你可以使用: DCOPY(Z,Y); DSCAL(B,Z); DAXPY(a,x,z);
您还可以阅读有关ATLAS项目的文章,其中包含有关代码优化关键方面的主要考虑因素(madd操作的存在,缓存特性,寄存器文件配置,指令延迟等)并尝试编写某些内容就像你的操作的代码生成器一样,管道执行各种操作并在各种变体之间执行搜索。
这是一个有趣的话题,我一直在使用显式管理的内存层次结构的异构多核架构上实现BLAS,就像Cell处理器一样。祝你好运!希望我的回答很有用!
答案 1 :(得分:0)
由于您使用的是MKL,因此可以使用扩展名为DAXPBY的y <-- ax + by
。然后您的操作将成为:
`z = ax + by`: DCOPY(n,z,1,y,1), then DAXPBY(n,a,x,1,b,z,1)
`y = ax`: DAXPBY(n,a,x,1,0,y,1)
您也可以尝试让编译器矢量化简单的标量代码;从理论上讲,这些简单的操作应该适合自动矢量化(当然,在实践中......)
答案 2 :(得分:0)
我建议您使用Fortran 95数组表示法编写自己的例程,看看编译器是否能够生成合适的代码。我怀疑它会,因为带宽有限的操作几乎被天真的实现最大化,即由大师编写的优化BLAS1库实现可能不会比未经优化的Netlib BLAS1快得多,除非数据已经驻留在缓存中(其中案例,矢量化会产生一些影响。)
我在过去进行了这样的比较,发现对于任何不在缓存中的向量,优化和未优化的BLAS1样式例程之间的差异可以忽略不计。