在 Julia 中,我主要看到在处理矩阵时加速和优化代码,更好,例如
- 按列而不是按行工作,这是 Julia 存储矩阵的方式。
-On 循环可以使用@inbounds
和@simd
宏
-欢迎您推荐的任何函数、宏或方法:D
但是,当我将 ArrayFire 包与存储在 GPU 上的矩阵一起使用时,上述示例似乎不起作用,CPU 和 GPU 中的类似代码似乎不支持在某些情况下运行速度慢得多的 GPU,我认为它应该不要那样,我认为问题在于编写代码的方式。欢迎任何帮助
GPU 计算应尽可能在优化的 GPU 内核上完成。索引 GPU 数组是一个小内核,它将一个值复制回 CPU。这对性能来说真的很糟糕,所以你几乎不应该索引 GPUArray 除非你必须这样做(这对于任何实现都是正确的!这只是一个硬件问题!)
因此,您应该编写广播(“矢量化”)代码,而不是为 GPU 编写循环代码。随着v0.6 广播的变化,广播操作几乎和循环一样高效(除非你遇到这个错误),所以没有理由在通用代码中避免它们。但是,在某些情况下,广播比循环更快,GPU 就是一个大例子。
让我解释一下为什么。当您执行代码时:
@. A = B*C + D*E
它降低到
A .= B.*C .+ D.*E
然后降低到:
broadcast!((b,c,d,e)->b*c + d*e,A,B,C,D,E)
请注意,在那里你有一个用于整个广播的融合匿名函数。对于 GPUArrays,然后将其覆盖,以便自动创建单个 GPU 内核,以逐元素执行此融合操作。因此,只需一个 GPU 内核即可完成整个操作!请注意,这比进行 GPU 计算的 R/Python/MATLAB 方式更有效,因为这些矢量化形式具有临时性,并且需要 4 个内核,但这没有临时数组并且是单个内核,这几乎就是如何如果您自己编写内核,您会编写它。因此,如果您利用广播,那么您的 GPU 计算将会很快。