Numpy: NumPy中的BLIS支持的跟踪器问题

创建于 2016-03-02  ·  97评论  ·  资料来源: numpy/numpy

这是一个有关NumPy中对BLIS支持的讨论的常规跟踪器问题。 到目前为止,我们已经在两个名义上无关的线程中对此进行了一些讨论:

因此,这是一个新问题,可以巩固以后的讨论:-)

当前要突出的一些突出问题:

CC: @tkelman @ matthew-brett @fgvanzee

15 - Discussion build

最有用的评论

当然可以在Windows上使用针对MSVC ABI的clang.exe构建BLIS。 我花了几个小时,这里是更改。 与OpenBLAS相比,所需的更改数量低得令人惊讶。
日志在这里。 所有BLIS和BLAS测试均通过。

所有97条评论

我看到BLIS已包含在site.cfg
可以支持libFLAME吗?

https://www.cs.utexas.edu/%7Eflame/web/libFLAME.html上的描述可能需要修复,但是据我了解,libFLAME实际上实现了LAPACK API。

@rgommers libflame确实提供了netlib LAPACK API,而libflame本身没有提供的所有实现。

FWIW,自此问题公开以来,BLIS取得了长足的进步。 例如,BLIS现在实现了运行时配置,并且在运行时基础结构方面已重新实现了其配置时配置。 除了更全面的测试套件外,BLIS现在还提供集成的BLAS测试驱动程序。 库自我初始化以及单片头生成(单个blis.h而不是500+个开发头)也已到位,这使得安装产品的管理更加容易。 它还为其静态和共享库构建遵循更标准化的库命名约定,其中包括soname 。 最后,它的构建系统比检查编译器和汇编程序的兼容性要聪明得多。 这就是我能想到的。

@fgvanzee谢谢。 在那种情况下,我+1以在numpy.distutils添加对此的支持。

我现在的时间真的很短,所以至少要到9月才能解决这个问题。 如果有人想解决这个问题,它应该相对简单(与gh-7294相同)。 很乐意帮助您进行故障排除/审查。

这听起来像是重大进展。 对于numpy / scipy(性能和稳定性而言),您距离OpenBLAS的可行替代方案还有多远?

(请注意,由于Fortran混乱,Windows上的conda仍然没有scipy-openblas:https://github.com/conda-forge/scipy-feedstock/blob/master/recipe/ meta.yaml#L14)

如果您想要兼容MSVC ABI的BLAS和LAPACK,仍然没有任何简单,完全开源的选项。 尽管如今有了clang-cl和flang,但问题不在于以前的编译器可用性,现在是构建系统的灵活性,并尝试使用库作者从未评估或支持的组合。 引用https://github.com/flame/blis/issues/57#issuecomment -284614032

@rgommers我要说的是,BLIS目前是OpenBLAS的相当可行的替代方案。 AMD放弃了ACML并完全采用BLIS作为其新的开源数学库解决方案的基础是足够可行的。 (我们有公司赞助商,并且在过去多年中一直由美国国家科学基金会赞助。)

在性能方面,确切的表征将取决于您正在查看的操作,浮点数据类型,硬件以及您感兴趣的问题大小范围。但是,总的来说,BLIS可以达到或超过OpenBLAS的能力。除了最小的问题大小(小于300左右)以外,所有其他语言的性能均为3级。 与OpenBLAS相比,它还采用了更加灵活的3级并行化策略(由于其整体式汇编内核设计)。

在稳定性方面,我想认为BLIS非常稳定。 我们努力对错误报告做出快速响应,并且由于过去五个月来社区的兴趣激增,我们已经能够识别并解决很多问题(主要是与构建系统相关的问题)。 这使最终用户和程序包管理器的用户体验变得流畅。

此外,请记住,BLIS从零时起就提供了BLAS类功能的超集,并通过两个独立于BLAS兼容性层的API来实现:

  • 显式类型的类似于BLAS的API
  • 隐式类型的基于对象的API

这不仅为已经拥有需要BLAS链接的软件的传统用户提供支持,而且为那些对从头开始构建自定义密集线性代数解决方案感兴趣的人们提供了一个很好的工具箱,这些人可能对BLAS界面没有特别的兴趣。

出于对现有BLAS实现以及BLAS API本身的种种不足而感到沮丧的原因,BLIS自2012年以来一直是我热爱的工作。它不会走开,只会变得越来越好。 :)

谢谢@tkelman。 Cygwin :( :(

听到来自在Linux / macOS上使用针对BLIS编译的numpy的人们的经验会很有趣。

感谢上下文@fgvanzee。 对我们来说,添加libFLAME支持并尝试SciPy基准测试套件将很有趣。

@rgommers回复:libflame:感谢您的关注。 请注意,libflame可以使用一些TLC。 它的形状不如BLIS好。 (我们没有我们想要的时间/资源来支持它,在过去的六年中,我们几乎100%的注意力都集中在使BLIS成为一个可以成为OpenBLAS可行且有竞争力的替代方案的地方。等)。

在某个时候,一旦BLIS成熟并且我们的研究途径已经用尽,我们可能会将注意力转移到libflame / LAPACK级别的功能上(例如,Cholesky,LU,QR因式分解)。 这可能采取将这些实现增量添加到BLIS的形式,或者可能涉及一个全新的项目来最终替代libflame。 如果是后者,它将被设计为利用BLIS中的较低级别的API,从而避免了某些功能调用和内存复制开销,这是当前通过BLAS不可避免的。 这只是我们期待调查的众多主题之一。

我已经没有多线程的Intel Skylake上使用NumPy 1.15和BLIS 0.3.2运行

Dotted two 4096x4096 matrices in 4.29 s.
Dotted two vectors of length 524288 in 0.39 ms.
SVD of a 2048x1024 matrix in 13.60 s.
Cholesky decomposition of a 2048x2048 matrix in 2.21 s.
Eigendecomposition of a 2048x2048 matrix in 67.65 s.

英特尔MKL 2018.3:

Dotted two 4096x4096 matrices in 2.09 s.
Dotted two vectors of length 524288 in 0.23 ms.
SVD of a 2048x1024 matrix in 1.11 s.
Cholesky decomposition of a 2048x2048 matrix in 0.19 s.
Eigendecomposition of a 2048x2048 matrix in 7.83 s.

在4.29秒内将两个4096x4096矩阵加点。

@homocomputeris对不起,我之前从未听说过用于描述对两个矩阵进行运算的“点”动词。 那是矩阵乘法吗?

@fgvanzee如今,BLIS中Windows支持的状态如何? 我记得以前几乎不支持将其构建在Windows上...

@fgvanzee和是的, numpy.dot是在Python中调用GEMM的传统方式。 (以一个奇怪的名称排序,但这是因为它在同一API中处理所有矢量,矢量矩阵,矩阵矩阵。)

@njsmith Windows的“本机”支持状态几乎不变。 不幸的是,我们仍然缺乏使这种支持成为现实的专业知识和兴趣。 但是,自Windows 10发布以来,似乎存在某种“ Windows Ubuntu”或某种形式的bash兼容环境。 这可能是获得Windows支持的更有希望的途径。 (但同样,我们小组中的任何人都无法在Windows上进行开发或使用Windows,因此我们甚至都没有研究该选项。)

好的,现在就发布最后一条...

@homocomputeris是用于这样的基准测试,它确实也有助于显示一些知名的库,例如OpenBLAS,因为否则我们不知道您的硬件有多快。

@fgvanzee说到本地的跨步有哪些限制? 它们是否必须是数据大小的对齐,正,非负,精确倍数...? (您可能还记得,numpy数组允许以字节为单位的完全任意步幅。)

@fgvanzee “ bash for Windows”实际上等效于在Windows上运行Linux VM –一种特别快速和无缝的VM,但它不是本机环境。 因此,好消息是您已经支持Windows bash了:-),但坏消息是它不能替代Windows的本机支持。

@njsmith我的结果与文章大致相同。
最新的MKL,例如:

Dotted two 4096x4096 matrices in 2.09 s.
Dotted two vectors of length 524288 in 0.23 ms.
SVD of a 2048x1024 matrix in 1.11 s.
Cholesky decomposition of a 2048x2048 matrix in 0.19 s.
Eigendecomposition of a 2048x2048 matrix in 7.83 s.

我要指出的是,我不知道如何编译BLIS以使用我的CPU可以优化的所有功能和多线程。 虽然MKL或多或少具有开箱即用的功能。

@njsmith感谢您的更新。 我同意,没有什么能比原生操作系统更好。 我也同意我们需要查看与其他库一起运行的基准测试,以便我们正确解释@homocomputeris的计时。

说到本地的跨步支持,这些天您对跨步有哪些限制? 它们是否必须是数据大小的对齐,正,非负,精确倍数...? (您可能还记得,numpy数组允许以字节为单位的完全任意步幅。)

@njsmith对齐了吗? 不,积极吗? 我认为我们已经解除了该限制,但是尚未对其进行彻底的测试。 数据类型的精确倍数? 是的,还是。

我将@devinamatthews带入讨论。 几个月前,我告诉他您要求大步前进的事情,而当时我有些记不清,他有很多要点/问题。 德文,您能记得您对此的担忧吗?如果是,将其表达给纳撒尼尔(Nathaniel)? 谢谢。

@homocomputeris您是否可以用size的其他值重新运行基准测试? 我想知道作者使用的值(4096)是2的幂是否对BLIS来说是一个特别糟糕的用例,而对于大多数应用程序而言却不是特别现实。 我建议改用4000(或3000或2000)。

@homocomputeris您是否说过BLIS结果是单线程的,而MKL结果是多线程的?

FWIW,我前段时间希望在Windows上构建BLIS。 目前的主要痛点是构建系统。 可能有可能使mingw的品牌使用clang生成与MSVC兼容的二进制文件。 我从来没有花时间去运行它,但是似乎有可能。

在实际的源代码中,情况还不错。 最近,他们甚至过渡到将宏用于其汇编内核,因此这成为消除Windows支持的又一障碍。 参见https://github.com/flame/blis/issues/220#issuecomment -397842370和https://github.com/flame/blis/pull/224。 看来源文件本身距离MSVC尚远一些宏/ ifdef,但这是我作为局外人的观点。 我也不知道如何使现有的BLIS makefile与MSVC一起使用。

@insertinterestingnamehere感谢您的不是在考虑Windows支持的情况下设计的。 此外,MSVC还支持C99吗? 如果没有,那是另一个障碍。 (BLIS需要C99。)

好吧,我在上面的示例中仅显示了BLIS与其他同类产品相当,这就是为什么我没有包含更具体的内容的原因。

但是,正如你问的:笑脸:

  • 英特尔酷睿i5-6260U处理器,具有最新的BIOS和Spectre / Meltdown的任何补丁
  • Linux 4.17.3-1-ARCH
  • 一切都用gcc 8.1.1编译20180531
  • NumPy 1.15.0rc1
  • 我为矩阵尺寸选择了质数

英特尔MKL 2018.3仅限2个线程(即我的物理CPU内核):

Dotted two 3851x3851 matrices in 1.62 s.
Dotted two vectors of length 492928 in 0.18 ms.
SVD of a 1925x962 matrix in 0.54 s.
Cholesky decomposition of a 1925x1925 matrix in 0.10 s.
Eigendecomposition of a 1925x1925 matrix in 4.38 s.

BLIS 0.3.2编译为
CFLAGS+=" -fPIC" ./configure --enable-cblas --enable-threading=openmp --enable-shared x86_64

Dotted two 3851x3851 matrices in 3.82 s.
Dotted two vectors of length 492928 in 0.39 ms.
SVD of a 1925x962 matrix in 12.82 s.
Cholesky decomposition of a 1925x1925 matrix in 2.02 s.
Eigendecomposition of a 1925x1925 matrix in 67.80 s.

因此,似乎至少在Unix / POSIX /类似系统中,NumPy应该肯定支持BLIS,因为我认为Windows用例是“如果可行,不要碰它”。
我唯一不知道的是MKL / BLIS和LAPACK / libFLAME之间的连接。 英特尔声称,除了BLAS之外,他们还有许多优化的东西,例如LAPACK,FFT等。

@fgvanzee为什么2的幂对BLIS不利? 如果需要最快的FFT,则在并置方法中很常见。

对于numpy的等,这将足以管理的MinGW / MSYS2建设---这就是我们与openblas目前做的Windows(虽然这有点一个黑客本身)。 它将使用范围限制为不涉及传递CRT资源的“传统” API,但这对于BLAS / LAPACK很好。

@fgvanzee关于C99的要点。 令人惊讶的是,WRT C99预处理器甚至还没有完全赶上MSVC 2017预处理器。 大概他们目前正在解决该问题(https://docs.microsoft.com/zh-cn/cpp/visual-cpp-language-conformance#note_D)。

@fgvanzee @njsmith这是我们需要做的以支持任意字节

1)修改界面。 对我而言,最方便的做法是在对象接口中添加类似stride_units标志的内容。
2)重构所有内部结构以仅使用字节跨距。 无论如何,这可能不是一个坏主意。
3)打包时,请检查数据类型是否对齐,如果没有,请使用通用打包内核。
a)通用包装内核也必须更新为使用memcpy 。 如果我们可以将其设置为使用文字大小参数,则不应太糟。
4)当C不对齐时,还要使用通过memcpy访问C的虚拟微内核。

这仅适用于输入和输出矩阵。 如果alphabeta可以是任意指针,那么会有更多问题。 请注意,在x86上,您可以很好地读取/写入未对齐的数据,但是其他体系结构(尤其是ARM)将是一个问题。 自动向量化时,编译器还会引入其他对齐问题。

@homocomputeris

  1. 我并不是要暗示二乘幂永远不会“在野外出现”,只是因为它们在基准测试中被过度代表了,这很可能是因为我们面向计算机的人喜欢使用二乘幂。 :)
  2. 这些基准测试结果确实相似。 如果下一个问题的答案为“否”,我会喜欢的,但是您是否有可能意外地将两个基准与MKL(或BLIS)链接在一起?
  3. 我完全同意在FFT相关应用中会产生2的幂。 我曾经从事信号处理工作,所以我了解。 :)
  4. 我对BLIS不能以二的幂进行很好的处理实际上并不是BLIS独有的关注。 但是,可能是我们观察到的现象在BLIS中更加明显,因此,相对于荒谬的优化解决方案(例如MKL),BLIS的净“惩罚性”。 问题如下:当矩阵的维数是2的幂时,它们的“前导维”也可能是2的幂。 (前导维对应于矩阵存储在列中时的列跨度,或行存储时在行中时的跨度。)让我们暂时假设行存储。 当前导维为2的幂时,元素(i,j)所在的缓存行与元素(i + 1,j),(i + 2,j)所在的缓存行处于相同的关联集,(i + 3,j)等有效-即后续行的相同元素。 这意味着,当gemm操作更新(例如,双精度实数6x8 C语言)时,这6行都映射到L1缓存中设置的相同关联性,因此不可避免地有一些在被删除之前被逐出。重用。 这些所谓的冲突遗漏会偶尔出现在性能下降中,并出现在我们的性能图中。 据我所知,要解决这种性能问题没有简单的方法。 我们已经打包/复制了矩阵A和B,因此不会对它们造成太大的影响,但是我们不能在不花费大量内存复制的情况下将矩阵C打包到更有利的引导尺寸。 (治愈可能比疾病还差。)现在,也许MKL可以缓解这种情况,也许切换到形状不同的微内核,以最大程度地减少冲突遗漏的数量。 也许他们不这样做,但是我知道BLIS不会尝试采取任何措施来减轻这种情况。 希望能回答您的问题。
  5. 没错,MKL不仅仅是BLAS + LAPACK功能。 但是,请记住,MKL是一种商业持有的封闭源解决方案。 尽管它可以“免费”用于非商业目的,但不能保证英特尔将来不会使MKL不再向公众开放或再次对其收费。 另外,对于想要了解实现,调整或修改实现,或在易于理解的构建基块上进行研究的计算机科学家来说,这并不是真正的好。 就是说,如果您要做的就是解决问题并继续前进,并且可以通过BLAS进行表达,那就太好了。 :)

@fgvanzee更新。 我的糟糕,由于某种原因,它使用MKL进行了编译,尽管我已将BLIS放在了配置中。
是否在LAPACK中实现SVD和EVD?

@homocomputeris是,LAPACK实现SVD和EVD。 我希望MKL的实施速度非常快。

但是,EVD有点模棱两可:存在广义特征值问题和Hermitian(或对称)EVD。 还有一个三对角EVD,但通常很少有人对此感兴趣,除了实施Hermitian EVD的人。

NumPy将在2018年底放弃对Python 2.7和3.4的支持,这将允许使用更新的符合C99的MSVC编译器,这是我们在正式2.7支持到期之前采取这一行动的原因之一。 有关最新MSVC编译器中C99支持的更多信息,请参见http://tinyurl.com/yazmczel 。 支持不完整(有人完成吗?),但可能就足够了。 在某些时候,我们将把NumPy本身移到C99,因为某些(英特尔)要求这样做以改善数值支持。

@charris感谢您提供此信息,Charles。 可能会实现的条件就足够了,但是直到尝试之前我们不确定。

无论如何,BLIS不需要击败MKL就可以开始被广泛采用。 它的直接竞争对手是OpenBLAS。

BLIS无需击败MKL就可以开始被广泛采用。 它的直接竞争对手是OpenBLAS。

完全同意。 MKL属于自己的联盟​​。

@njsmith只是好奇:numpy社区会对新API /功能产生多大的兴趣,使它们能够在混合精度和/或混合域中执行gemm ? 就是说,每个操作数可以是不同的数据类型,其计算的精度(可能)与A和B?之一或两者不同。

@fgvanzee有意思的是,尽管潜在的组合数量令人困惑。 但是目前,我们进行类型转换,这需要时间并占用内存。 尽管布尔值可能是唯一不会因溢出而遭受无法弥补的影响的类型,但我也一直在考虑为整数类型优化例程的想法。

而且总是有float16。 ML人士可能对这些功能更感兴趣。 @GaelVaroquaux有什么想法吗?

@charris是的,案件数量可能令人生畏。 gemm有128种类型组合,假设有四个传统浮点数据类型,并且该数字从转置/共轭参数以及矩阵存储可能性中排除了任何组合膨胀(在这种情况下,它会55,296)。

即使通过低性能的参考实现来完全实现128种情况也将是值得注意的,并且以更高的性能(将开销最小化)来实现将是非常特殊的。 (而且,由于BLIS基于对象的基础,如果我们要实现这一点,则在附加目标代码方面将花费很少。)

如果您对此感兴趣,请在接下来的几天/几周内观看我们的项目。 :)

BLIS前叉安全吗?

无论如何,BLIS不需要击败MKL就可以开始被广泛采用。 它的直接竞争对手是OpenBLAS。

确实。 老实说,我无法使NumPy + BLAS在我的系统上运行,但是从我之前引用的文章来看,它们的性能似乎非常相似。
如果链接到NumPy,libFLAME可能会加快LAPACK操作。

另一个有趣的问题是,将AMD的BLIS / libFLAME叉子安装在最新的Zen CPU上,以查看它们是否有所改进。 鉴于有问题的英特尔处理器,它变得更加有趣。

在Linux和Windows上,当前numpy的官方轮子包括OpenBLAS的预构建副本,因此在这些平台上,获取副本的最快方法是pip install numpy 。 (当然这是不完全公平的,因为例如,该版本是使用与用于本地构建BLIS的编译器不同的编译器构建的,但是它可以提供一些思路。)

BLIS前叉安全吗?

@jakirkham我与@devinamatthews谈到了这一点,他似乎认为答案是肯定的。 BLIS按需生成线程(例如,在调用gemm ),而不是像OpenBLAS那样维护线程池。

但是,我们很好奇:numpy期望/喜欢/依赖哪种线程模型? 在连续调用许多非常小的问题的用例中,您是否需要线程池来减少开销? (BLIS的按需线程不太适合这种用法。)

编辑:同样,您是否需要pthreads,还是可以使用OpenMP?

谢谢(你的)信息。

那么是否同时使用pthreads和OpenMP? FWIW存在GCC的OpenMP的已知问题,@ogrisel )。 在Python中通过multiprocessing模块进行分叉是最常见的并行策略之一,因此能够以分叉安全的方式使用线程(出于上述原因,最好使用pthreads)在Python中通常很重要。 尽管如今有更多选择,例如使用fork-exec之类的loky之类的东西。

诚然,纳撒尼尔比我更了解这件事,但是由于我已经开始写此评论,因此IIUC NumPy不会通过外部库(例如BLAS)使用线程本身。 尽管NumPy确实经常释放GIL ,这允许在Python中进行线程化有些有效。 Joblib,Dask等之类的东西都利用了这种策略。

关于线程池,有趣的是您问这个问题,因为我前几天正在介绍一种ML技术以最大限度地提高性能,该技术使用NumPy / SciPy在Python中执行一系列BLAS例程。 使用OpenBLAS和合理数量的内核,即使在Python中没有使用显式线程(包括NumPy和SciPy),该例程也能够在例程的长度上使内核饱和,这仅仅是因为OpenBLAS在线程的长度上使用了线程池。常规。 因此,是的,线程池非常宝贵。

另一方面,BLIS是否处理动态体系结构检测? 这对于构建可以一次构建并部署在各种不同系统上的构件非常重要。

@jakirkham感谢您的评论。 我想观察到的没有线程池的代价将取决于您要传入的矩阵操作数的大小以及您要执行的操作。 我假设gemm是您所针对的典型操作(如果我错了,请更正),但是您认为典型的问题大小是多少? 我想如果您反复进行矩阵乘法(其中A,B和C为40x40,但对于400x400或更大的矩阵乘法),那么BLIS创建/联接模型的成本将会体现出来。 (TBH,您可能不应该期望从并行化40x40问题开始就可以大大提高速度。)

另一方面,BLIS是否处理动态体系结构检测? 这对于构建可以一次构建并部署在各种不同系统上的构件非常重要。

是。 此功能是在不久前的2017年下半年实现的。BLIS现在可以针对所谓的“配置族”,并通过一些启发式方法(例如cpuid在运行时选择要使用的特定子配置。 intel64amd64x86_64

@fgvanzee我实际上认为小型矩阵的性能是OpenBLAS的弱点之一,因此如果BLIS再次变慢,这将有点令人担忧...人们肯定在各种情况下都使用numpy,因此我们真的很重视库“只需工作”,无需针对特定情况进行调整。 (我想这与经典的稠密线性代数设置有些不同,在经典的线性代数设置中,两个最重要的情况是算法作者运行基准测试以及专家与专门的系统管理员一起运行为期一周的超级计算机作业。)例如,人们经常使用numpy和3x3矩阵。

在某些情况下,适当地处理此问题可能只是注意到问题太小而完全跳过线程。 对于3x3的宝石,最佳选择可能是尽可能愚蠢。

但是,如果BLIS开始广泛部署,这种调整(甚至是线程池与无线程池的事情)可能是社区会采取的措施。

实际上,这使我想起了:我上周与某人交谈,他知道他想在他的库中调用单线程gemm,因为他正在更高级别上管理线程,而他对标准blas库唯一的方法感到沮丧。通过全局设置来控制它,可以从一个随机库内部调用它。 BLIS的本机API是否允许用户在逐个调用的基础上控制线程配置? 我猜是的,因为IIRC在BLAS兼容性层之外根本没有任何全局配置?

我实际上认为小型矩阵的性能是OpenBLAS的弱点之一,因此,如果BLIS再次变慢,那就有点令人担忧了……人们肯定在各种情况下都使用numpy,因此我们非常重视“工作”,而无需针对特定情况进行调整。

我知道希望它“正常工作”,但我正在尝试与您保持现实和诚实。 如果您遇到3x3问题,而性能对您而言确实很重要,那么您甚至不应该使用BLIS。 我并不是说BLIS的运行速度会比3x3的天真三重循环慢10倍,但这并不是BLIS的实现所擅长的问题大小。

听到您对OpenBLAS的一些小问题有些不满意,我感到很惊讶。 你的参考点是什么? 仅仅是性能比大问题低吗? 对于小问题,要获得最高的性能,就需要与大问题不同的策略,这就是为什么大多数项目以一个或另一个为目标,然后仅次优地处理非目标案例的原因。

在某些情况下,适当地处理此问题可能只是注意到问题太小而完全跳过线程。 对于3x3的宝石,最佳选择可能是尽可能愚蠢。

我同意临界值是理想的。 但是确定临界值在何处并非易事,并且肯定会因体系结构(以及跨3级操作)而异。 因此这很有可能,但是尚未实现(或深思熟虑)。

但是,如果BLIS开始广泛部署,这种调整(甚至是线程池与无线程池的事情)可能是社区会采取的措施。

是。

实际上,这使我想起了:我上周与某人交谈,他知道他想在他的库中调用单线程gemm,因为他正在更高级别上管理线程,而他对标准blas库唯一的方法感到沮丧。通过全局设置来控制它,可以从一个随机库内部调用它。

来自多线程应用程序的顺序gemm是我们最喜欢考虑的用例之一。 (提醒:如果顺序gemm是他唯一的用例,他可以简单地配置禁用多线程的BLIS。但是,让我们假设他想构建一次,然后再决定线程。)

BLIS的本机API是否允许用户在逐个调用的基础上控制线程配置? 我猜是的,因为IIRC在BLAS兼容性层之外根本没有任何全局配置?

即使在启用多线程的情况下配置BLIS,默认情况下也禁用并行性(一个线程)。 这是他解决问题的第二种方法。

但是,假设他想在运行时更改并行度。 可以在运行时设置BLIS中的并行性。 但是,它仍然涉及BLIS通过setenv()getenv()内部设置和读取环境变量。 (有关更多详细信息,请参见Multithreading Wiki 。)因此,我不确定这是否对您的朋友而言是个大难题。 我们想要实现一个API,在其中可以以更具编程性的方式(不涉及环境变量)来指定线程,但是目前还没有。 主要是关于界面; 基础设施到位。 问题的一部分是,我们多年来都接受过培训(例如OMP_NUM_THREADS等),以便在并行化时指定一个数字,这是BLIS偏爱的信息的过度简化。 gemm算法中有五个循环,其中四个可以并行化(将来有五个循环)。 我们可以从一个数字中猜测,但是由于它取决于硬件拓扑,因此通常不是理想的。 因此,这是阻碍这方面进展的一部分。

@devinamatthews有没有机会沿着相同的脉络添加TBLIS?

如果您遇到3x3问题,而性能对您而言确实很重要,那么您甚至不应该使用BLIS。 我并不是说BLIS的运行速度会比3x3的天真三重循环慢10倍,但这并不是BLIS的实现所擅长的问题大小。

我并不担心要为3x3问题获得最佳性能(尽管显然,如果可以得到它,那就太好了!)。 但举一个极端的例子:如果numpy是使用BLIS作为其基础线性代数库进行编译的,并且某些用户使用numpy在其代码中写入a @ b ,我肯定希望它不会以慢10倍的速度运行而不是天真的实现。 期望用户在多次使用3x3矩阵之前重建numpy实在是太难了:-)。 尤其是由于同一程序在一个位置上乘以3x3的矩阵也可能在另一位置上乘以1000x1000矩阵。

提醒:如果顺序式gemm是他唯一的用例,则他可以简单地配置禁用多线程的BLIS。 但是,假设他要构建一次,然后再决定线程。

他正在交付一个Python库。 他希望他的用户可以使用他的库,并将其与其他库和自己的代码结合在一起,并在同一过程中一起运行。 他的库使用的是GEMM,他可能无法控制甚至不了解的其他一些代码也可能希望使用GEMM。 他希望能够控制对GEMM调用线程,而不会意外地影响其他无关的呼叫GEMM可能在同一过程中发生的事情。 理想情况下,他无需携带自己的GEMM副本就可以做到这一点,因为这样做很烦人,而且从概念上讲,程序必须包含两个大型图书馆的副本因此您可以获得一个整数变量number_of_threads两个副本。 这更有意义吗?

我绝对希望它最终不会比单纯的实现慢10倍。

现在,我考虑了一下,如果它在极小的(3x3)问题上比天真慢几倍,我不会感到惊讶,但是交叉点会很低,可能只有16x16。 这是一个很容易就可以进行创可贴的问题。 (我想对所有3级操作都这样做。)

他正在交付一个Python库。 他希望他的用户可以使用他的库,并将其与其他库和自己的代码结合在一起,并在同一过程中一起运行。 他的库使用的是GEMM,他可能无法控制甚至不了解的其他一些代码也可能希望使用GEMM。 他希望能够控制对GEMM的调用的线程,而不会意外影响在同一过程中可能发生的对GEMM的其他不相关的调用。 理想情况下,他无需携带自己的GEMM副本就可以做到这一点,因为这样做很烦人,而且从概念上讲,程序必须包含两个大型图书馆的副本因此您可以获得一个整数变量number_of_threads的两个副本。 这更有意义吗?

是的,这很有帮助-感谢您提供详细信息。 听起来他将是我们目前尚不存在的线程API的理想人选。 (就我个人而言,我认为环境变量约定是一种疯狂的疯狂行为,并且已经多次向我的合作者表达了我的看法。那对许多HPC用户/基准测试者来说相当方便,因此我们必须使用适当的运行时API来完成,该API不会排除环境变量的使用,以使每个人都保持满意。)

您介意向他传达这绝对是我们的关注吗? 我将与罗伯特依。 他可能有足够的兴趣批准我在此上花费的时间,宜早不宜迟。 (线程API已经存在了一段时间。)

当然可以在Windows上使用针对MSVC ABI的clang.exe构建BLIS。 我花了几个小时,这里是更改。 与OpenBLAS相比,所需的更改数量低得令人惊讶。
日志在这里。 所有BLIS和BLAS测试均通过。

@isuruf感谢您抽出

至于拉取请求,我有一些评论/请求(都很少),但我将就拉取请求本身开始对话。

PS:很高兴您能够找出f2c错误。 我只将libf2c的足够部分导入了BLAS测试驱动程序源(编译为libf2c.a ),以便可以链接东西,尽管它确实需要在头文件中进行一些黑客操作。 (我不喜欢维护Fortran代码,以至于我不愿看f2c的C而不是Fortran,以防万一。

英特尔MKL 2018.3:

Dotted two 4096x4096 matrices in 2.09 s.
Dotted two vectors of length 524288 in 0.23 ms.
SVD of a 2048x1024 matrix in 1.11 s.
Cholesky decomposition of a 2048x2048 matrix in 0.19 s.
Eigendecomposition of a 2048x2048 matrix in 7.83 s.

关于上面使用的基准的一个词。 罗伯特提醒我,除非我们知道该基准测试(或numpy?)如何实现Cholesky,EVD和SVD,否则这些操作的结果就不会那么有意义。 例如,如果将netlib LAPACK代码用于Cholesky分解,则算法的块大小将是错误的(远非理想)。 此外,根据numpy链接到MKL的方式,它可能会进一步扭曲事物,因为MKL除了快速gemm ,还具有自己的Cholesky因式分解实现,因此与MKL。

我知道您可能只是出于对性能的总体了解而使用它,这很好。 只是要了解,细节中可能隐藏着魔鬼,除了非常近似的比较之外,不允许使用它。

通常,numpy会像对可用的LAPACK或类似LAPACK的库那样推迟操作。 MKL的构建几乎可以肯定是使用MKL内附带的LAPACK的优化分支。 BLIS构建可能正在使用参考LAPACK或类似的东西。

从某种意义上讲,这很公平:如果您尝试选择一个numpy配置来执行快速SVD,则MKL具有可用的调整版本而BLIS没有提供相关的调整,这是相关的。 (我相信OpenBLAS介于两者之间:他们在库中提供了LAPACK的修改版本,但是比MKL的版本更接近参考实现。)但是可以肯定的是,您是否要了解BLIS是什么以及为什么要这样做?结果看起来像这样,重要的是要记住,不仅纯GEMM效率,SVD / etc还有更多的东西。

从某种意义上讲,这是公平的:

我理解并同意。 由于有些人使用像先前提出的基准那样的基准来衡量单个硬件上的绝对性能(即,判断一种实现相对于峰值性能的性能如何),而有些人则使用它来比较各种实现,这一事实使情况变得复杂。 我认为Robert对Cholesky等人的评论。 比后者更针对前者。

@njsmith @insertinterestingnamehere @rgommers @charris由于Isuru的快速工作,我们能够将他基于供应商的Windows支持完善并合并到BLIS的master分支中。 请看看,让我们知道这是否以及在何种程度上解决了Windows对numpy的支持问题。

@fgvanzee您可以链接到PR吗?

您可以链接到PR吗?

当然,在这里它是。

最初的构建设置很棒! 至少从理论上讲,它应该足以允许在Windows上使用BLIS构建numpy。 稍后可以添加诸如构建dll或支持MinGW之类的东西。

关于在这种情况下使用的依赖项要注意的一件事:pthreads-win32是LGPL。 IDK不过需要做些什么。

许可是一个难题。 我确实知道一些大公司,其法律政策使其难以使用LGPL之类的“ copyleft”许可证,而“宽松”许可证则不成问题。 无论是否合理,将LGPL代码添加到NumPy / SciPy代码库或转盘中绝对会引起关注。

我们不在这里将其添加到代码库中。 用轮装运LGPL组件不是问题。 现在,我们正在提供带有运行时异常的GPL的gfortran dll。 见gh-8689

确实。 如果这些公司也喜欢MKL,也不会感到惊讶。

我们只需要确保LGPL组件未静态链接即可。

@jakirkham感谢您的评论。 我想观察到的没有线程池的代价将取决于您要传入的矩阵操作数的大小以及您要执行的操作。 我假设gemm是您所针对的典型操作(如果我错了,请更正),但是您认为典型的问题大小是多少? 我想如果您反复进行矩阵乘法(其中A,B和C为40x40,但对于400x400或更大的矩阵乘法),那么BLIS创建/联接模型的成本将会体现出来。 (TBH,您可能不应该期望从并行化40x40问题开始就可以大大提高速度。)

主要是GEMM和SYRK是典型的。 GEMV有时会出现,但如果可能的话,通常会合并到大型GEMM操作中。

对于我们来说,至少有1个维数在10 ^ 6个元素的数量级上是非典型的。 另一个可能在10 ^ 3到10 ^ 6之间。 所以变化很大。 要使用线程池,我们需要做些什么吗?还是会自动发生? 另外,如果进程分叉,线程池的行为如何?

另一方面,BLIS是否处理动态体系结构检测? 这对于构建可以一次构建并部署在各种不同系统上的构件非常重要。

是。 此功能是在不久前的2017年下半年实现的。BLIS现在可以针对所谓的“配置族”,通过运行时通过启发式方法(例如cpuid指令)选择要使用的特定子配置。 受支持的系列的示例是intel64,amd64,x86_64。

首先,我们一直使用使用Nehalem的旧计算机,一直到Broadwell。 也许一些较新的个人计算机具有Kaby Lake。 因此,如果我们使用不受支持的内在函数在古老的计算机上运行,​​那么能够充分利用我们提供的体系结构非常重要,同时又不会崩溃。 Flame的子配置是否支持此范围,是否内置了额外的代码以在不同的体系结构上分配适当的内核? 这有多精细? 在构建过程中我们需要做些什么来确保这些内核存在吗?

@jakirkham使用x86_64配置进行构建可以使您:

  • Penryn(包括Nehalem和任何其他64位SSSE3 Intel芯片)
  • 桑迪桥(包括常春藤桥)
  • Haswell(+ Broadwell,Skylake,Kaby Lake和Coffee Lake,尽管对于最后三个而言可能并非完全最佳)
  • Xeon Phi(第一代和第二代,如果需要,我们也可以做第三代)
  • Skylake SP / X / W(可能在Cannon Lake上也非常接近最佳)
  • 推土机/推土机/压路机/挖掘机
  • 锐龙/ EPYC

请注意,其中一些确实需要足够新的编译器和/或binutils版本,但仅在构建机器上需要。

AFAIK libflame没有针对任何体系结构的专用内核,这完全取决于BLIS。

@jakirkham我们必须添加一个

AFAIK libflame没有针对任何体系结构的专用内核,这完全取决于BLIS。

这基本上是正确的。 尽管libflame确实有一些用于应用Givens旋转的内在内核(当前只有SSE),但是这些内核不属于libflame,而是因为BLIS在编写时不存在而存在,因此没有其他地方可以使用。安置他们。 最终,这些内核将被重写和更新,并重新放置到BLIS中。

Flame的子配置是否支持此范围,是否内置了额外的代码以在不同的体系结构上分配适当的内核? 这有多精细? 在构建过程中我们需要做些什么来确保这些内核存在吗?

@jakirkham我不确定您所说的“火焰”是什么意思。 我们有两种产品:libflame和BLIS。 尽管libflame需要关注并且可能需要重写,但是过去几年我几乎所有的注意力都放在了BLIS上。

如果将“ Flame”(火焰)替换为“ BLIS”,则答案为“是”。

它有多细?

不确定您的意思,但是BLIS中的内核支持没有OpenBLAS中的内核支持广泛。 例如,我们经常不优化复杂域trsm 。 子配置通过某种组合使用内核。 通过cpuid选择子配置。 您完全可以通过子配置获得“注册”的内核。 有关螺母和螺栓的详细信息,请参见配置Wiki。

在构建过程中我们需要做些什么来确保这些内核存在吗?

如果需要运行时硬件检测,则可以在配置时将配置族(例如intel64x86_64 )作为目标,而不是特定的子配置(或auto ,它选择特定子配置)。 而已。

要使用线程池,我们需要做些什么吗?还是会自动发生? 另外,如果进程分叉,线程池的行为如何?

正如我之前在该线程中所说的那样,BLIS不使用线程池。 而且我请德文谈谈叉子的安全性(他似乎认为分叉不会有问题)。

FYI,BLIS conda软件包可用于conda-forge上的linux,osx,windows。 (当前正在构建dev分支,正在等待发布)。 软件包是在启用pthreads和x86_64配置的情况下构建的。

他正在交付一个Python库。 他希望他的用户可以使用他的库,并将其与其他库和自己的代码结合在一起,并在同一过程中一起运行。 他的库使用的是GEMM,他可能无法控制甚至不了解的其他一些代码也可能希望使用GEMM。 他希望能够控制对GEMM的调用的线程,而不会意外影响在同一过程中可能发生的对GEMM的其他不相关的调用。

@njsmith我已经与Robert谈过,他可以提高工作的优先级。 (此外,在简要研究中,我发现BLIS中的竞争条件会在两个或多个应用程序线程尝试使用不同程度的并行性时表现出来。修复该竞争条件将同时满足诸如以下方面的API相关需求:你的朋友。)

@jakirkham我们在英特尔的联络人之一@jeffhammond告诉我们,OpenMP实现通常在内部使用线程池模型。 因此,他不鼓励我们在BLIS中冗余地实现线程池。

现在,正如您所建议的,可能是numpy需要/偏爱pthread,在这种情况下,我们可能会回到发生在fork / join样式pthreads API下的实际fork / join。

那么是否同时使用pthreads和OpenMP?

另外,我意识到我忘了回答这个问题。 BLIS的多线程并行性是可配置的:它可以使用pthreads或OpenMP。 (但是,由于我们依赖于用于库初始化的pthread_once() ,因此请勿将其与BLIS对pthreads的无条件运行时依赖相混淆。)

不幸的是,除非OpenMP实现(例如GOMP)通常对分叉变得更加健壮,否则在Python中这并不是一个安全的选择。 特别是堆栈中没有NumPy的堆栈。

不幸的是,除非OpenMP实现(例如GOMP)通常对分叉变得更加健壮,否则在Python中这并不是一个安全的选择。 特别是堆栈中没有NumPy的堆栈。

很公平。 因此,听起来numpy将依靠--enable-threading=pthreads配置选项通过BLIS进行多线程。

使用pthreads进行编译时,是否有一些公共API可以获取一些编程控制,从而避免在与调用numpy的Python进程/线程池进行嵌套并行处理时避免出现超额预订问题?

更具体地说,这是我要寻找的公共符号类型:

https://github.com/tomMoral/loky/pull/135/files#diff -e49a2eb30dd7db1ee9023b8f7306b9deR111

类似于在https://github.com/IntelPython/smp中为MKL和OpenMP执行的操作。

使用pthreads进行编译时,是否有一些公共API可以获取一些编程控制,从而避免在与调用numpy的Python进程/线程池进行嵌套并行处理时避免出现超额预订问题?

@ogrisel很好的问题,Olivier。 有一种方法可以在运行时设置线程参数,但目前已通过全局语义完成。 它是次优的,因为(除了是全局的,而不是基于gemm的每次调用),它通过环境变量来传递。

我目前正在对底层代码进行较小的重新设计,以允许某人使用BLIS的所谓“专家”子API之一将额外的数据结构传递给gemm ,这将允许呼叫者根据每次呼叫指定并行化策略应该是什么。 前面提到的数据结构将允许人们指定单个线程,并让BLIS尽其所能自动找出从何处获得并行性,或矩阵乘法算法中每个循环的并行度(就像BLIS所喜欢的那样)。

无论哪种方式,我认为这种新方法都能满足您的需求。 我已经完成了更改的一半,所以我距离将新功能推送到github大约只有一周的时间。 如果这个计划听起来像对您有用的东西,和/或您对此主题还有其他疑问或要求,请告诉我。

PS:我看了看您提供的链接。 这些符号都是为线程的全局设置而设置的。 我提出的解决方案不会排除全局设置的问题,但它的设计目的不是唯一的选择。 因此,想要使用最多8个内核/线程的人可以使应用程序产生2个线程,并且每个线程都调用gemm实例,该实例获得4向并行性。 或3个应用程序线程,其中两个使用2向并行性调用gemm ,而第三个使用4向并行性调用。 (你明白了。)

它通过环境变量。

这是什么意思? 一旦已经在特定的Python进程中初始化了默认/全局BLIS线程池的大小,是否可以使用Python中的ctypes重新配置它的大小?

它通过环境变量。

这是什么意思?

@ogrisel我的意思是,我们在BLIS中有一个小的API来设置或获取线程数,类似于OpenMP中的omp_get_num_threads()omp_set_num_threads() 。 但是,这些BLIS API函数被实现为对getenv()setenv()调用。 这仅仅是历史事实,因为BLIS的原始用例之一是在shell中设置一个或多个环境变量(例如bash ),然后执行一个BLIS链接的应用程序,因此在现在,仅需简单地基于该环境变量方法即可; 它从来都不是指定用于并行处理的线程数的最终,完美的方法。

一旦在特定的Python进程中初始化了BLIS线程池,是否可以使用Python中的ctypes重新配置它的大小?

BLIS没有显式使用线程池。 相反,我们使用创建/连接模型通过pthread提取并行性。 但是可以,至少在原则上,在初始化BLIS之后,应用程序(或调用库)可以在运行时通过函数调用更改线程数。 (但是,我不知道这在实践中是否可行,因为我不知道Python如何处理试图设置/获取环境变量的BLIS。)但是正如我之前提到的,一旦完成一些修改,应用程序/库将能够在调用第3级操作时基于每个调用指定自定义并行化方案。 例如,首先初始化一个小的struct数据类型,然后将该struct传递给BLIS API的扩展“专家”版本,价格为gemm 。)对于不需要/想要它们的人来说,将使环境变量不必要。 希望这能回答您的问题。

非常感谢您的澄清。 每次呼叫专家API很有趣,但需要numpy维护特定的API才能将其公开给Python级调用者。 我不确定我们是否想要那个。 我认为对于numpy用户而言,有一种方法可以更改全局(进程级别)并行性级别的当前值。 我个人不介意是否可以通过更改env变量的当前值来实现,只要将此更改考虑到随后的BLAS-3调用中即可。

@charris float16对于某些机器学习工作负载可能确实很有趣,至少在预测时,尽管我对此没有经验。

我认为对于numpy用户而言,有一种方法可以更改全局(进程级别)并行性级别的当前值。 我个人不介意是否可以通过更改env变量的当前值来实现,只要将此更改考虑到随后的BLAS-3调用中即可。

很高兴知道。 如果是这样的话,那么BLIS距离numpy准备好使用了。 (我只想先进行这些进行中的修改,同时也可以解决以前未注意到的竞争条件。)

最好不要依赖每次调用都要重新检查的环境变量,因为getenv并不是超级快,因此以后删除它可能很有意义。 (而且,我不认为它甚至可以保证是线程安全的吗?)但是bli_thread_set_num_threads API调用应该没问题,因为即使BLIS始终停止调用getenv ,然后API调用可以调整以保持正常工作。

从长远来看,我认为有必要在numpy中公开一些超出标准的BLAS API。 首先,使BLIS具吸引力的一件事就是它提供了其他BLAS库所没有的功能,例如能够扩展跨矩阵的功能,并且正在进行着以多种方式扩展BLAS API的工作。

我们不想在numpy的API中对特定于库的详细信息进行硬编码(例如,我们不希望np.matmul开始采用与BLIS的JC,IC,JR和IR参数相对应

我没有看到的一件事是索引精度。 大多数系统提供的库似乎都使用32位整数,这对于当今的某些应用程序是一个限制。 如果所有索引均为64位,则在某个时候会很好,这可能需要我们提供库。 我不知道我们目前在索引大小方面正在做什么。 @ matthew-brett我们仍在使用32位整数进行编译吗?

@charris BLIS中的整数大小可以在配置时配置:32或64位。 此外,您可以独立于内部整数大小来配置BLAS API中使用的整数大小。

实际上,这使我想起了:我上周与某人交谈,他知道他想在他的库中调用单线程gemm,因为他正在更高级别上管理线程,而他对标准blas库唯一的方法感到沮丧。通过全局设置来控制它,可以从一个随机库内部调用它。

@njsmith我已经修复了前面提到的竞争条件,并且还实现了线程安全的每次调用多线程API。 请将您的朋友指向fa08e5e (或该提交的任何后代)。 多线程文档也已更新,并通过基本示例引导读者进行选择。 提交目前在dev分支上,但我希望很快将其合并到master 。 (我已经将代码通过了大部分步伐。)

编辑:链接已更新,以反映较小的修订提交。

作为受支持类型的可能补充, long double呢? 我注意到有些体系结构开始支持四精度(仍然在软件中),并且我希望在某些时候扩展精度将被intel的四精度取代。 我不认为这是紧迫的事情,但我认为在所有这些年之后事情开始发展。

@charris我们正处于考虑支持bfloat16和/或float16的早期阶段,尤其是因为它们的机器学习/ AI应用程序,但是我们也意识到对double double的需求

@charris根据https://en.wikipedia.org/wiki/Long_double,$#$ long double可以表示多种含义:

  • 使用12B或16B存储在x87中实现的80位类型
  • MSVC的双精度
  • 双精度
  • 四倍精度
    由于含义不明确,不仅取决于硬件,而且还取决于所使用的编译器,因此对于库而言,这是完全的灾难,因为ABI的定义不明确。

从性能的角度来看,由于没有SIMD版本,所以我看不到float80有任何上行空间(即x87长的double)。 如果可以用BLIS编写double double的SIMD版本,那应该会更好。

软件中的float128实现至少比硬件中的float64慢一个数量级。 最好编写一个新的float128实现,该实现跳过所有FPE处理并适合SIMD。 libquadmath中的实现虽然正确,但不值得像BLIS这样的高性能BLAS实现的注意。

是的,这是个问题。 我认为扩展精度不值得付出努力,对四精度的需求参差不齐,对大多数事情来说,双精度是有好处的,但是当您需要它时,就需要它。 我不担心性能,不是速度而是精度。 请注意,我们只是扩展了对具有四精度长双精度ARM64的ARM64的支持,这当然是软件实现,但是我希望在某个时候可以采用硬件,并且可以进行一些测试并准备就绪。

激动地看到这种进步!

作为记录,我是@njsmith所指的那个人,他对控制软件的线程感兴趣。 在预测时,我的工作量令人尴尬地并行,并且矩阵乘法相对较小。 因此,我宁愿并行处理较大的工作单元。

大约一年前,我在为By打包PyPi并添加Cython绑定方面做了一些工作: https :

我发现Blis像这样的C扩展很容易打包。 对我而言,主要障碍是Windows支持。 从内存来看,这是C99问题,但我可能记错了。

我添加的Cython接口可能很有趣。 特别是,我使用的是Cython的融合类型,因此对于float和double类型,只有一个nogil函数可以用内存视图或原始指针调用。 为更多类型添加更多分支也没有问题。 融合类型基本上是模板:它们允许编译时条件执行,而开销为零。

我会很高兴维护一个独立的Blis程序包,保持轮子的稳定性,保持一个不错的Cython接口,等等。我认为将它作为一个单独的程序包而不是集成在numpy中会很好。 然后,我们可以公开更多Blis的API,而不受其他BLAS库支持的限制。

@honnibal对不起,对此主题的回复

感谢您的留言。 我们总是很高兴看到其他人对BLIS感到兴奋。 当然,如果您决定进一步集成到python生态系统(应用程序,库,模块等)中,我们将在需要时建议您。

至于Windows支持,请查看@isuruf最近添加的Windows ABI的clang / appveyor支持。 上次我从他那里听到消息,它按预期运行,但是我们在UT的Windows上未进行任何开发,因此我自己也无法掌握。 (尽管Isuru曾经向我指出,我可以以类似于Travis CI的方式注册承租人。)

另外,如果您对每次通话的线程使用有任何疑问,请告诉我。 (我已经更新了多线程文档以涵盖此主题。)

BLIS 0.5.2开始,我们有一个性能文档,该文档展示了BLIS的单线程和多线程性能以及BLAS的其他实现,包括在包括Marvell ThunderX2在内的多种核心架构上的一组代表性数据类型和3级操作。 ,英特尔Skylake-X,英特尔Haswell和AMD Epyc。

因此,如果numpy社区想知道BLIS如何与其他领先的BLAS解决方案相提并论,我邀请您快速浏览!

非常有趣,谢谢@fgvanzee。

我必须查找Epyc-似乎这是基于Zen(可能在某个时候更新为Zen +?)体系结构的品牌名称。 也许重命名为Zen更好? 对于我们的用户群而言,Ryzen / Threadripper是更有趣的品牌,他们可能认识到Zen,但可能不认识Epyc。

Epyc是AMD服务器行的名称。 它是过去AMD Opteron产品的后继产品。

不幸的是,由于代码依赖于矢量ISA(例如AVX2),CPU核心微体系结构(例如Ice Lake)和SOC /平台集成(例如Intel Xeon Platinum处理器),因此BLIS没有独特的方式来标记其体系结构目标。 )。 BLIS在某些情况下(例如Dunnington)使用微体系结构代码名称,但这并不适合所有人。

@fgvanzee您可以考虑添加与GCC march / mtune / mcpu名称相对应的别名...

@rgommers BLIS中涵盖Ryzen和Epyc的子配置实际上已经命名为zen ,因为它同时捕获了这两种产品。

至于Ryzen / Threadripper还是Epyc是更有趣的品牌(甚至对于numpy用户而言),我会这样说:如果我只能对一个AMD Zen系统进行基准测试,那它将是最高端的Epyc,因为:(a)使用与Ryzen类似的微体系结构; (b)它给了我最多64个物理核心(而且,作为奖励,这些核心以某种类似于NUMA的新颖配置进行排列); (c)最大程度地强调了BLIS和其他实现。 这基本上就是我们在这里所做的。

幸运的是,现在没有规则说我只能对一个Zen系统进行基准测试。 :)但是,还有其他障碍,特别是在获得访问权方面。 我目前无法使用任何Ryzen / Threadripper系统。 如果/当我获得访问权限时,我将很乐意重复实验并相应地发布结果。

Jeff指出了我们面临的一些命名陷阱。 通常,我们根据微体系结构来命名子配置和内核集,但还有更多细微差别。 例如,我们在Haswell,Broadwell,Skylake,Kaby Lake和Coffee Lake上使用haswell配置。 这是因为它们基本上都共享相同的向量ISA,这几乎是BLIS内核代码所关心的。 但这是一个实现细节,几乎不需要用户关注。 如果您使用./configure auto ,则无论它们被命名为zen还是haswell或其他任何值,您几乎总会获得最佳的子配置和内核集。 就目前而言,在最佳选择线程方案时,您仍然需要采取更多动手方法,这就是Jeff提到的SoC /平台集成的地方。

@jeffhammond感谢您的建议。 我曾经考虑过添加这些别名。 但是,我不认为这是值得的。 它将大大增加配置注册表的混乱程度,并且首先关注它的人员可能已经知道我们的子配置和内核集的命名方案,因此不会因缺少某些微体系结构修订而感到困惑该文件(或config目录中)的名称。 现在,如果BLIS需要手动识别子配置,例如通过./configure haswell ,那么我认为规模肯定会倾斜,从而支持您的建议。 但是./configure auto效果很好,所以目前我看不到这种需要。 (如果您愿意,可以就此主题打开一个问题,以便我们可以在社区成员之间进行更广泛的讨论。如果有足够的需求,我总是愿意改变主意。)

是的,命名总是很复杂:)感谢@fgvanzee@jeffhammond的回答

#13132和#13158相关

讨论进行了一些; 要在numpy中正式支持BLIS,还需要解决哪些剩余问题?

天真的,我尝试从conda-forge(cf https://github.com/numpy/numpy/issues/14180#issuecomment-525292558)用BLIS运行numpy测试,对我来说,在Linux上,所有测试都通过了(但是也许我错过了什么)。

还尝试在相同的环境中运行test scipy测试套件,并且在scipy.linalg (cf https://github.com/scipy/scipy/issues/10744)中存在许多失败的情况,以防有人对此发表评论那。

请注意,来自conda-forge的BLIS使用ReferenceLAPACK(netlib)作为LAPACK实现,该实现使用BLIS作为BLAS实现,而不是libflame

关于conda-forge上的BLIS选项,我是否认为它是单线程的(不同于OpenBLAS选项)?

将conda-forge讨论移至conda-forge better可能更好

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

manuels picture manuels  ·  3评论

keithbriggs picture keithbriggs  ·  3评论

kevinzhai80 picture kevinzhai80  ·  4评论

ghost picture ghost  ·  4评论

qualiaa picture qualiaa  ·  3评论