julia - 点语法导致向量加法速度降低 200 倍
问题描述
我正在试验向量加法和分量取幂的速度,当我遇到一个使用点向量化语法的奇怪结果时。
非矢量化版本,
julia> @time exp(randn(1000) + randn(1000))
几次运行后大约需要 0.001 秒。它还给出了从 0.6 开始的弃用警告。
如果我对指数函数进行矢量化,
julia> @time exp.(randn(1000) + randn(1000))
我得到了 4 倍的加速,大约 0.00025 秒。
但是,如果我将指数函数和向量相加都向量化,
julia> @time exp.(randn(1000) .+ randn(1000))
我的速度大幅下降到 0.05 秒左右。为什么会出现这种情况?什么时候应该避免使用点语法以最大限度地提高性能?
解决方案
.+
创建一个匿名函数。在 REPL 中,每次都会创建此函数,并且会破坏您的计时结果。此外,使用全局(动态类型,即不可推断)会减慢所有示例的速度。在任何实际情况下,您的代码都将在一个函数中。当它在一个函数中时,它只在第一次调用该函数时编译。例子:
> x = randn(1000); y = randn(1000);
> @time exp(x + y);
WARNING: exp(x::AbstractArray{T}) where T <: Number is deprecated, use exp.(x) instead.
Stacktrace:
[1] depwarn(::String, ::Symbol) at .\deprecated.jl:70
[2] exp(::Array{Float64,1}) at .\deprecated.jl:57
[3] eval(::Module, ::Any) at .\boot.jl:235
[4] eval_user_input(::Any, ::Base.REPL.REPLBackend) at .\REPL.jl:66
[5] macro expansion at C:\Users\Chris\.julia\v0.6\Revise\src\Revise.jl:775 [inlined]
[6] (::Revise.##17#18{Base.REPL.REPLBackend})() at .\event.jl:73
while loading no file, in expression starting on line 237
0.620712 seconds (290.34 k allocations: 15.150 MiB)
> @time exp(x + y);
0.023072 seconds (27.09 k allocations: 1.417 MiB)
> @time exp(x + y);
0.000334 seconds (95 allocations: 27.938 KiB)
>
> @time exp.(x .+ y);
1.764459 seconds (735.52 k allocations: 39.169 MiB, 0.80% gc time)
> @time exp.(x .+ y);
0.017914 seconds (5.92 k allocations: 328.978 KiB)
> @time exp.(x .+ y);
0.017853 seconds (5.92 k allocations: 328.509 KiB)
>
> f(x,y) = exp.(x .+ y);
> @time f(x,y);
0.022357 seconds (21.59 k allocations: 959.157 KiB)
> @time f(x,y);
0.000020 seconds (5 allocations: 8.094 KiB)
> @time f(x,y);
0.000021 seconds (5 allocations: 8.094 KiB)
请注意,通过将其放入一个函数中,它会编译和优化。这是Julia Performance Tips中提到的主要内容之一。
推荐阅读
- c++ - Cuda 基本程序(将值写入矩阵和 std:cout 不起作用);主函数未启动
- c - 如何将字体设置为用户使用字体选择器选择的字体?
- php - 删除获取请求的 url .php 扩展名和参数?
- vue.js - Vue js如何使用props值到v-model
- nginx - 使用 nginx 反向代理丢失 POST 请求正文
- arrays - 如何将 json 数据显示到 laravel 刀片中?
- php - php sqlsrv 通过多台服务器连接到一个特定的数据库
- java - 如何通过 LLRP 从 EPC RFID 标签读取用户数据(内存)?
- typescript - 如何修复 no-unsafe-any 规则?
- ios - 如何在 Swift 中使用查询语句检索数据?