【发布时间】:2021-02-18 13:23:29
【问题描述】:
在 julia 中,可以在实数集合上找到(据说)min/minimum 和 max/maximum 的有效实现。
由于这些概念不是为复数唯一定义的,我想知道这些函数的参数化版本是否已经在某处实现。
我目前正在对感兴趣的数组的元素进行排序,然后取最后一个值,据我所知,这比找到具有最大绝对值(或其他)的值要昂贵得多。
这主要是为了在复杂数组上重现 max 函数的 Matlab 行为。
这是我当前的代码
a = rand(ComplexF64,4)
b = sort(a,by = (x) -> abs(x))
c = b[end]
可能的函数调用如下所示
c = maximum/minimum(a,by=real/imag/abs/phase)
编辑使用提供的解决方案在 Julia 1.5.3 中进行一些性能测试
function maxby0(f,iter)
b = sort(iter,by = (x) -> f(x))
c = b[end]
end
function maxby1(f, iter)
reduce(iter) do x, y
f(x) > f(y) ? x : y
end
end
function maxby2(f, iter; default = zero(eltype(iter)))
isempty(iter) && return default
res, rest = Iterators.peel(iter)
fa = f(res)
for x in rest
fx = f(x)
if fx > fa
res = x
fa = fx
end
end
return res
end
compmax(CArray) = CArray[ (abs.(CArray) .== maximum(abs.(CArray))) .& (angle.(CArray) .== maximum( angle.(CArray))) ][1]
Main.isless(u1::ComplexF64, u2::ComplexF64) = abs2(u1) < abs2(u2)
function maxby5(arr)
arr_max = arr[argmax(map(abs, arr))]
end
a = rand(ComplexF64,10)
using BenchmarkTools
@btime maxby0(abs,$a)
@btime maxby1(abs,$a)
@btime maxby2(abs,$a)
@btime compmax($a)
@btime maximum($a)
@btime maxby5($a)
长度为 10 的向量的输出:
>841.653 ns (1 allocation: 240 bytes)
>214.797 ns (0 allocations: 0 bytes)
>118.961 ns (0 allocations: 0 bytes)
>Execution fails
>20.340 ns (0 allocations: 0 bytes)
>144.444 ns (1 allocation: 160 bytes)
长度为 1000 的向量的输出:
>315.100 μs (1 allocation: 15.75 KiB)
>25.299 μs (0 allocations: 0 bytes)
>12.899 μs (0 allocations: 0 bytes)
>Execution fails
>1.520 μs (0 allocations: 0 bytes)
>14.199 μs (1 allocation: 7.94 KiB)
长度为 1000 的向量的输出(与 abs2 进行的所有比较):
>35.399 μs (1 allocation: 15.75 KiB)
>3.075 μs (0 allocations: 0 bytes)
>1.460 μs (0 allocations: 0 bytes)
>Execution fails
>1.520 μs (0 allocations: 0 bytes)
>2.211 μs (1 allocation: 7.94 KiB)
一些备注:
- 清晰排序(如预期)会减慢操作速度
- 使用
abs2可以节省大量性能(也是预期的)
总结:
- 由于内置函数将在 1.7 中提供此功能,因此我将避免使用额外的
Main.isless方法,尽管它被认为是性能最好的方法,但不要修改我的 julia 的核心 -
maxby1和maxby2不分配任何内容 -
maxby1感觉更具可读性
因此获胜者是 Andrej Oskin!
编辑 n°2 使用更正的 compmax 实现的新基准
julia> @btime maxby0(abs2,$a)
36.799 μs (1 allocation: 15.75 KiB)
julia> @btime maxby1(abs2,$a)
3.062 μs (0 allocations: 0 bytes)
julia> @btime maxby2(abs2,$a)
1.160 μs (0 allocations: 0 bytes)
julia> @btime compmax($a)
26.899 μs (9 allocations: 12.77 KiB)
julia> @btime maximum($a)
1.520 μs (0 allocations: 0 bytes)
julia> @btime maxby5(abs2,$a)
2.500 μs (4 allocations: 8.00 KiB)
【问题讨论】:
标签: julia