感谢您的量子更新,丹尼尔.以下几行可能难以接受,但请相信我,还有更多的事情需要考虑.我研究过HPC /并行计算问题,这些问题的矩阵大小为N [TB]; N> 10和他们稀疏的伴奏,所以一些经验可能对你的进一步观点有用.

警告:不要指望任何晚餐免费送达

将一段代码并行化的愿望听起来像是一种越来越多的当代重新表达的法术力.问题不在于代码,而在于此类移动的成本.

经济是头号问题. Amdahl定律,最初由Gene Amdahl制定,没有考虑[PAR] – 过程 – 设置[PAR] – 过程 – 最终结果和成本的成本.终止,确实必须在每个现实世界的实施中支付.

如果愿意更好地理解这个主题并预先计算实际的“最小”-subProblem-“大小”,可以随意阅读更多关于开销严格的Amdahl定律重新制定的帖子,其中[PAR]的总和-overheads至少可以从实际工具中得到证明,用于将subProblem的并行拆分引入N_trully_ [PAR] _processes(不是任何“just” – [CONCURRENT],但是true- [PARALLEL] – 这些都不是等于).

Python可能会获得一剂类固醇以提高性能:

Python是一个伟大的原型生态系统,而numba,numpy和其他编译扩展有助于提升性能,远远超过原生GIL步进python(co – )处理通常提供的.

在这里,您尝试强制执行numba.jit()几乎免费安排作业,只需通过自动jit() – 时间词法分析器(您抛出代码),这应该“理解”您的全局目标(做什么),并提出一些矢量化技巧(如何最好地组装一堆CPU指令,以实现此类代码执行的最大效率).

这听起来很容易,但事实并非如此.

Travis Oliphant的团队在numba工具方面取得了巨大的进步,但是当我试图转换代码并组装一个代码时,不要期望在.jit() – lexer代码分析中实现任何形式的自动化操作是现实和公平的.更高效的机器指令流,以实现高级任务的目标.

@guvectorize?这里?真的吗?

由于[PSPACE]的大小调整,你可能会立即忘记要求numba以某种方式有效地“填充”GPU引擎的数据,其内存占用量远远落后于GPU-GDDR sizings(根本不是说 – “这种数学上的“GPU”内核大小 – “微小”处理只能相乘,可能在[PAR]中,但后来在[SEQ]中求和.

(重新) – 使用数据加载GPU需要大量时间.如果支付了这笔费用,那么GPU内存延迟对于“微小的”-GPU内核经济性来说也不是很友好 – 你的GPU-SMX代码执行必须支付~350-700 [ns]才能获取数字(很可能不会自动重新对齐以便在后续步骤中使用最佳合并的SM缓存重用,你可能会注意到,你从来没有,让我重复一遍,永远不要重复使用单个矩阵单元,所以缓存本身不会在每个矩阵单元350~700 [ns]下提供任何东西),而智能纯numpy矢量化代码可以在每个单元格中以不到1 [ns]的速度处理矩阵矢量积,即使是最大的[PSPACE ] -footprints.

这是比较的标准.

(分析将更好地显示这里的事实,但这个原则事先是众所周知的,没有测试如何将几TB数据移动到GPU结构上,只是为了实现这一点.)

最糟糕的坏消息:

考虑到矩阵A的记忆规模,预期的效果越差,矩阵表示的存储的稀疏组织最有可能破坏大多数(如果不是全部)可能的性能增益,这些性能可通过密集的numba矢量化技巧实现.矩阵表示,因为高效内存获取高速缓存行重用的可能性几乎为零,稀疏性也将破坏任何简单的方法来实现矢量化操作的紧凑映射,这些很难保持能够轻松转换为高级CPU – 硬件矢量处理资源.

可解决问题的清单:

>总是更好地预先分配向量Ax = np.zeros_like(A [:,0])并将其作为另一个参数传递给numba.jit() – 编译的代码部分,以避免重复支付额外的[PTIME ,PSPACE] – 用于创建(再次)新内存分配的成本(如果向量被怀疑在外部协调的迭代优化过程中使用,则会更多)

>总是更好地指定(为了缩小普遍性,为了产生代码性能)至少numba.jit(“f8 [:](f4 [:],f4 [:,:],…)”) – 调用接口指令

>始终查看所有numba.jit() – 可用的选项及其各自的默认值(可能会将版本更改为版本)以适应您的具体情况(禁用GIL并更好地将目标与numba硬件功能保持一致将始终有助于代码的数字密集部分)

@jit( signature = [ numba.float32( numba.float32, numba.int32 ), # # [_v41] @decorator with a list of calling-signatures
numba.float64( numba.float64, numba.int64 ) #
], #__________________ a list of signatures for prepared alternative code-paths, to avoid a deferred lazy-compilation if undefined
nopython = False, #__________________ forces the function to be compiled in nopython mode. If not possible, compilation will raise an error.
nogil = False, #__________________ tries to release the global interpreter lock inside the compiled function. The GIL will only be released if Numba can compile the function in nopython mode, otherwise a compilation warning will be printed.
cache = False, #__________________ enables a file-based cache to shorten compilation times when the function was already compiled in a previous invocation. The cache is maintained in the __pycache__ subdirectory of the directory containing the source file.
forceobj = False, #__________________ forces the function to be compiled in object mode. Since object mode is slower than nopython mode, this is mostly useful for testing purposes.
locals = {} #__________________ a mapping of local variable names to Numba Types.
) #____________________# [_v41] ZERO <____ TEST *ALL* CALLED sub-func()-s to @.jit() too >>>>>>>>>>>>>>>>>>>>> [DONE]
def r...(...):
...