偉大な質問@tparkerと偉大な答え@コリンボワーズ。両者について考えようとしているうちに、ストレートな古い学校のジュリアンの方法 - for
-loopを試してみました。同じ要素の長いベクトルの重要な入力の結果が速かったので、このメモを追加します。また、関数名allequal
は言及するのに十分なようです。
allequal_1(x) = all(y->y==x[1],x)
allequal_2(x) = foldl(==,x) # another way but doesn't short-circuit :(
@inline function allequal_3(x)
length(x) < 2 && return true
e1 = x[1]
i = 2
@inbounds for i=2:length(x)
x[i] == e1 || return false
end
return true
end
ベンチマーク:だからここ変異体である
julia> using BenchmarkTools
julia> v = fill(1,10_000_000); # long vector of 1s
julia> allequal_1(v)
true
julia> allequal_2(v)
true
julia> allequal_3(v)
true
julia> @btime allequal_1($v);
9.573 ms (1 allocation: 16 bytes)
julia> @btime allequal_2($v);
10.585 ms (0 allocations: 0 bytes)
julia> @btime allequal_3($v);
6.853 ms (0 allocations: 0 bytes)
UPDATE:ショート機会があるときに、ベンチマークにもう一つの重要な場合があります。だから、(commmentに要求されるように):
julia> v[100] = 2
2
julia> allequal_1(v),allequal_2(v),allequal_3(v)
(false, false, false)
julia> @btime allequal_1($v);
108.946 ns (1 allocation: 16 bytes)
julia> @btime allequal_2($v);
10.325 ms (0 allocations: 0 bytes)
julia> @btime allequal_3($v);
68.221 ns (0 allocations: 0 bytes)
allequal_2
運賃ひどく、それがショートしないように、第2のバージョンは。
すべて等しいことは、for
のバージョンがベースでallequal
になるはずです。
ありがとう、 'foldl'はまさに私が探していた機能です。第三の実装がなぜより速いのかについての '@ inbounds'を超える理由があると思いますか? – tparker
Julia Baseは、一般的な機能を組み合わせて構築し、多くの実装を高水準かつ抽象的にすることによって、Julia Baseがどのように構築されるのが本当に好きです。 'reduce.jl'を見てください。私は 'allequal'(それは実際にBaseにあるべきではありませんが)は、ハイパー最適化されたカスタムループを作るのではなく、' all'のようないくつかの一般的なコンストラクトの上に構築されたものです。このようにして、 'all'のパフォーマンスを向上させることで、それに依存するすべての機能が向上します。 – DNF
BTW。 'foldl'は短絡していませんので、ここでは間違いなく最適です。 – DNF