ОБНОВЛЕНИЕ: Ради полноты я добавил отличное решение Мэтта Б. в набор тестов (и также заставил transpose
в f4
сгенерировать новыйматрица, а не ленивый вид).
Вот несколько разных подходов (ваш базовый случай f0
):
f0(x) = [ i[2] for i in findmax(x, dims = 2)[2]][:,1]
f1(x) = getindex.(argmax(x, dims=2), 2)
f2(x) = [ argmax(vec(x[n,:])) for n = 1:size(x,1) ]
f3(x) = [ argmax(vec(view(x, n, :))) for n = 1:size(x,1) ]
f4(x) = begin ; xt = Matrix{Float64}(transpose(x)) ; [ argmax(view(xt, :, k)) for k = 1:size(xt,2) ] ; end
f5(x) = map(argmax, eachrow(x))
Используя BenchmarkTools
, мы можем проверить эффективностькаждый (я установил x = rand(100, 200)
):
julia> @btime f0($x);
76.846 μs (13 allocations: 4.64 KiB)
julia> @btime f1($x);
76.594 μs (11 allocations: 3.75 KiB)
julia> @btime f2($x);
53.433 μs (103 allocations: 177.48 KiB)
julia> @btime f3($x);
43.477 μs (3 allocations: 944 bytes)
julia> @btime f4($x);
73.435 μs (6 allocations: 157.27 KiB)
julia> @btime f5($x);
43.900 μs (4 allocations: 960 bytes)
Так что подход Мэтта - довольно очевидный победитель, так как он выглядит просто как синтаксически более чистая версия моего f3
(эти два, вероятно, компилируются вчто-то очень похожее, но я думаю, что это было бы излишним, чтобы проверить это).
Я надеялся, что f4
может иметь преимущество, несмотря на временное создание, созданное путем создания экземпляра transpose
, поскольку он может работать настолбцы матрицы, а не строки (Юлия является основным языком столбцов, поэтому операции со столбцами всегда будут выполняться быстрее, поскольку элементы синхронизированы в памяти).Но этого, по-видимому, недостаточно, чтобы преодолеть недостаток временного.
Обратите внимание, если вам когда-либо понадобится полный CartesianIndex
, то есть индекс строки и столбцамаксимум в каждой строке, то, очевидно, подходящее решение просто argmax(x, dims=2)
.