在Julia中,我主要看到,当我处理矩阵时,要去除和优化代码,效果更好,例如
-按列而不是按行工作,这是Julia存储矩阵的方式。
-开环可以使用@inbounds
和@simd
宏
-欢迎您推荐任何函数、宏或方法:D
但当我使用存储在GPU上的矩阵的ArrayFire包时,上面的例子似乎不起作用,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)
请注意,在那里您有一个用于整个广播的融合匿名函数。对于GPU阵列,这将被覆盖,这样就可以自动创建一个单独的GPU内核来执行这种融合操作。因此,只需要一个GPU内核就可以完成整个操作!请注意,这甚至比R/Python/MATLAB进行GPU计算的方式更有效,因为这些矢量化形式有临时数组,这里需要4个内核,但它没有临时数组,是一个单独的内核,如果你自己编写内核,这几乎正是你应该写的。因此,如果你利用广播,那么你的GPU计算将很快。