你如何“扩展”BLAS子程序?

时间:2012-04-14 19:08:35

标签: math fortran linear-algebra lapack blas

通常,为某个唯一操作定义BLAS子例程。例如,

DAXPY必须y <-- ax + y

DSCAL必须x = ax

我希望实现的目标是:

z = ax+byy = ax

如何“扩展”BLAS的子程序,以便我可以执行上述操作? (这些操作不一定相互关联)

我试过了:

  • 声明一个假人,然后DCOPY将假人移动到所需的向量。比如,DCOPY(dummy,x); DSCAL(a,dummy),DCOPY(y,dummy)

  • 创建我自己的OpenMP实现

  • 使用DCOPY(y,a*x)等技巧获取y = ax

但问题是,这些方法似乎都没有给我一个确定的答案,因为这是解决这个问题的最佳方法。我知道我应该“配置文件,配置文件,配置文件”,而不是问我,但我已经尝试了所有这些,但每次我改变矢量一点,早期最好的方法突然变得最差,反之亦然。

此外,

  • 我的目的是为了实现最佳表现。
  • 我知道优化这些操作可能不会给我带来很大的性能提升,但我正在努力保存每一皮秒。
  • FWIW,我正在链接到英特尔MKL

3 个答案:

答案 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样式例程之间的差异可以忽略不计。