DAXPY、DCOPY、DSCAL 是不是有点过头了?

计算科学 表现 正则 布拉斯
2021-12-14 05:45:18

我通过将它链接到英特尔 MKL 在 FORTRAN 中实现了 CG。

当有这样的陈述时:(参考维基百科

 p=r; 
 x=x+alpha*p
 r=r-alpha*Ap;

QMR中的类似(数量更多)

v_tld = r;
y = v_tld;
rho = norm( y );
w_tld = r;
z = w_tld;
xi = norm( z ); (and more)

使用 BLAS 1 级实现(例如 DAXPY、DCOPY、DSCAL)是否有意义? 我提出问题的动机是:

  1. 我有 2 个算法的实现。我只将 Norms 和 MatVecs 链接到 MKL 的一个;复制、缩放和添加是由 Fortran 的内在函数完成的,而另一个可能的子程序由 BLAS 执行。

  2. 我认为没有什么能比 BLAS 更快。但是,事实证明,我使用 Fortran 内部函数的代码比使用 BLAS 1 级子程序的代码运行速度快 100%(FWIW,这不是一个小问题,它解决了一个 13k x 13k 的密集系统,它填满了我的 4 GB 内存)。我在 2 个线程(在 2 核机器上)上ifort QMR.f90 -mkl同时运行MKL_DYNAMIC=TRUE

  3. 曾经问过一个关于 BLAS 扩展的 SO问题,但是当我尝试将 BLAS Level 1 包含到我的代码中时,我的代码变得越来越慢。

我做错了什么还是预期的?

y = 2.89*x此外,尝试扩展 BLAS 以执行诸如by之类的非显而易见的操作是否有意义DCOPY(n,2.89*x,1,y,1) or even DSCAL then DCOPY


同样有趣的是,DDOT提高DNRM2性能。我将其归因于这样一个事实,即由于它们执行双精度乘法,因此将它们并行放置可能会有所帮助。

补充问题:您何时决定 BLAS 1 级操作是否真的有助于提高性能?

添加:目前,我在 i3 2.13 GHz 笔记本电脑上运行,具有 4 GB RAM 和 Debian 64 位Proc 信息但是,我在配备 24 GB RAM 的 Intel Xeon 12 核工作站上得到了类似的答案。

4个回答

如果您的目标真的是尽可能多地发挥性能,那么记住以下几点很重要:

  1. (BLAS) 库可能尚未针对您的确切系统/配置进行调整。
  2. 库开发人员会犯错误。

供应商调整的 BLAS 库当然应该是您的默认方法,但如果您花时间对单个内核进行计时并注意到其他一些实现更快,那么请务必使用其他实现。错过向量内在函数的使用可能会导致巨大的性能差异。

对于像daxpydscal这样的简单例程,您最好的选择可能是一个利用向量内在函数的手写循环。

鉴于现在优化编译器的状态,我认为在线性 BLAS 例程中没有太多巫术,例如DAXPYDCOPYDSCAL,您的编译器还不会这样做,例如 SSE 向量化和循环展开。

如果代码相同,那么您的例程和对 MKL 的 BLAS 的调用之间的唯一区别是函数调用的开销以及 MKL 可能试图在那里做的任何额外的魔法。如果是这种情况,您的代码和 MKL 的代码之间的差异应该是一个常数,与问题/向量大小无关。

这个问题有这个问题的有趣回声它也DAXPY用作一个例子。

BLAS 标准实际上对函数参数的正确性进行了多项检查,这在许多情况下是不必要的。请参阅daxpy.f. 此外,常量 likeINCX通常在编译时为您所知,但实现可能不会假定。BLAS 调用交叉编译单元,我不知道有任何编译器能够在不打开整个程序优化的情况下优化这些单元。

  • 一个有趣的旁注是,英特尔编译器现在可以识别 BLAS 3 矩阵-矩阵乘法循环,并将此代码转换为等效的xgemm调用,并启用足够的优化。

BLAS1 函数代表一组因计算强度低而受到带宽限制的内核。特别是,这些内核每次内存访问都会执行 O(1) 次失败。这意味着在现代硬件上,它们运行在峰值的一小部分,基本上你无能为力。BLAS1 的最佳实现将检查对齐情况并取模 FPU 矢量长度并在带宽峰值处执行,这可能是计算峰值的 5-10%。

当您在源代码中明确编写这些操作时,一个好的编译器会立即识别它们并内联一些与上面提到的 BLAS1 等效的最佳实现。但是,由于编译器对上下文了解得更多,它可以避免某些分支(不是那么重要)和函数调用开销,并可能在代码中执行可能被函数调用阻塞的高阶转换一个不透明的图书馆。

您可以执行各种实验来确定实际影响代码性能的因素。它们非常明显,所以我不会在这里列出它们。