如何在Julia中加速多个广播 这个朱丽亚函数似乎相当低效(比Pythran / C++代码更慢一个数量级,即使在朱丽亚预热之后)…
我想只是我写得不对。。。在茱莉亚,怎样才能加速这种“多重广播”?我想/希望我不需要花费这些循环 在第一个答案后编辑 谢谢大家!!在我的设置中,Pythran解决方案(就地和异地)的速度仍然快1.5到2倍(没有OpenMP)。有没有办法激活Julia中的SIMD指令?还是另一种加速CPU计算的方法 Python代码:如何在Julia中加速多个广播 这个朱丽亚函数似乎相当低效(比Pythran / C++代码更慢一个数量级,即使在朱丽亚预热之后)…,julia,pythran,Julia,Pythran,我想只是我写得不对。。。在茱莉亚,怎样才能加速这种“多重广播”?我想/希望我不需要花费这些循环 在第一个答案后编辑 谢谢大家!!在我的设置中,Pythran解决方案(就地和异地)的速度仍然快1.5到2倍(没有OpenMP)。有没有办法激活Julia中的SIMD指令?还是另一种加速CPU计算的方法 Python代码: from transonic import jit @jit def broadcast(a): return 10 * (2*a**2 + 4*a**3) + 2 / a
from transonic import jit
@jit
def broadcast(a):
return 10 * (2*a**2 + 4*a**3) + 2 / a
@jit
def broadcast_inplace(a):
a[:] = 10 * (2*a**2 + 4*a**3) + 2 / a
在@simd
建议后编辑
似乎@simd
不是开箱即用的,即只需将其添加到行的开头
ERROR: LoadError: LoadError: Base.SimdLoop.SimdError("for loop expected")
Stacktrace:
[1] compile(::Expr, ::Bool) at ./simdloop.jl:54
[2] @simd(::LineNumberNode, ::Module, ::Any) at ./simdloop.jl:126
[3] include at ./boot.jl:317 [inlined]
[4] include_relative(::Module, ::String) at ./loading.jl:1044
[5] include(::Module, ::String) at ./sysimg.jl:29
[6] exec_options(::Base.JLOptions) at ./client.jl:231
[7] _start() at ./client.jl:425
我猜必须扩展for循环,但是代码(I)变得不那么可读,(ii)不再独立于维度
似乎我们有这样一种情况,简单的Python/Numpy代码可以用Pythran比Julia更快地得到加速(除非Julia中有加速的方法?将来的Julia版本可能会解决这个问题)。有趣的…广播所有这样的操作:
julia> function my_multi_broadcast2(a)
@. 10 * (2*a^2 + 4*a^3) + 2 / a
end
my_multi_broadcast2 (generic function with 1 method)
区别在于,在10*(2*a.^2+4*a.^3)+2./a
中,您实际上没有利用广播融合,因为*
和两个+
没有广播
写@。10*(2*a^2+4*a^3)+2/a
相当于10.*(2.*a.^2.+4.*a.^3)。+2./a
这里是性能的比较
julia> @btime my_multi_broadcast($arr);
58.146 ms (18 allocations: 61.04 MiB)
julia> @btime my_multi_broadcast2($arr);
5.982 ms (4 allocations: 7.63 MiB)
<> Pythran与C++相比,我们得到了大约10x的加速比?
最后,请注意,如果您可以通过编写以下命令在适当的位置变异arr
:
julia> function my_multi_broadcast3(a)
@. a = 10 * (2*a^2 + 4*a^3) + 2 / a
end
my_multi_broadcast3 (generic function with 1 method)
julia> @btime my_multi_broadcast3($arr);
1.840 ms (0 allocations: 0 bytes)
这两种方法都更快,并且零分配(我不知道您是想修改
arr
,还是创建一个新的数组,所以我展示了这两种方法)。实际上,您说的是“@”。10…
相当于…,然后忘记在括号内点乘法。它应该是10.*(2.*a.^2.+4.*a.^3.+2./a
DNF-谢谢,修复了。这就是为什么在本例中,@.
是一件好事。您可以尝试添加@simd
,如果这还不够,请编写一个手动循环。广播应自动使用simd指令,但目前存在一个性能缺陷,对于这样的大型融合表达式,它不会发生。我希望1.2版能修复它。
julia> function my_multi_broadcast3(a)
@. a = 10 * (2*a^2 + 4*a^3) + 2 / a
end
my_multi_broadcast3 (generic function with 1 method)
julia> @btime my_multi_broadcast3($arr);
1.840 ms (0 allocations: 0 bytes)