Есть ли способ поменять местами столбцы в O (1) в Julia? - PullRequest
3 голосов
/ 02 ноября 2019

Я взял Джулию для выполнения численного анализа и пытался реализовать полное разложение LU (например, пытаясь получить разложение LU, которое было бы максимально стабильным). Я думал, что лучший способ сделать это - найти максимальное значение для каждого столбца, а затем преобразовать столбцы в порядке убывания их максимальных значений.

Есть ли способ избежать замены каждого элемента двух столбцов и вместо этогоделать что-то вроде смены двух ссылок / указателей?

Ответы [ 3 ]

2 голосов
/ 02 ноября 2019

Следуя ответу @ longemen3000, вы можете использовать представления для замены столбцов. Например:

julia> A = reshape(1:12, 3, 4)
3×4 reshape(::UnitRange{Int64}, 3, 4) with eltype Int64:
 1  4  7  10
 2  5  8  11
 3  6  9  12

julia> V = view(A, :, [3,2,4,1])
3×4 view(reshape(::UnitRange{Int64}, 3, 4), :, [3, 2, 4, 1]) with eltype Int64:
 7  4  10  1
 8  5  11  2
 9  6  12  3

Тем не менее, хорошая ли это стратегия зависит от шаблонов доступа. Если вы будете использовать элементы V один или несколько раз, эта стратегия view подойдет. Напротив, если вы получаете доступ к элементам V много раз, вам может быть лучше сделать копию или переместить значения на месте, так как это цена, которую вы платите один раз, тогда как здесь вы платите косвенную стоимость каждый раз, когда получаете доступ к значению.

1 голос
/ 02 ноября 2019

Просто для «полноты», если вы действительно хотите поменять местами столбцы,

function swapcols!(X::AbstractMatrix, i::Integer, j::Integer)
    @inbounds for k = 1:size(X,1)
        X[k,i], X[k,j] = X[k,j], X[k,i]
    end
end

просто и быстро.

Фактически, в отдельном тесте для малыхМатрицы это даже быстрее, чем подход view, упомянутый в других ответах (представления не всегда бесплатны):

julia> A = rand(1:10,4,4);

julia> @btime view($A, :, $([3,2,1,4]));
  31.919 ns (3 allocations: 112 bytes)

julia> @btime swapcols!($A, 1,3);
  8.107 ns (0 allocations: 0 bytes)
1 голос
/ 02 ноября 2019

в julia есть макрос @view, который позволяет вам создать массив, который является просто ссылкой на другой массив, например:


A = [1 2;3 4]
Aview = @view A[:,1] #view of the first column
Aview[1,1] = 10

julia> A
2×2 Array{Int64,2}:
 10  2
 3  4

с указанным, при работе с конкретными типами чисел(Float64, Int64 и т. Д.), Юлия использует непрерывные блоки памяти с прямым представлением типа числа. то есть массив чисел julia не является массивом указателей, где каждый элемент массива является указателем на значение. если значения массива могут быть представлены конкретным двоичным представлением (например, массивом структур), то используется массив указателей.

Я не специалист по компьютерным наукам, но я заметил, что лучше, чтобы ваши данные были плотно упакованы, если при обработке чисел использовалось много указателей.

Еще один другой случай - это Sparse Arrays,базовое представление julia разреженного массива представляет собой массив индексов и массив значений. здесь вы можете просто поменять местами индексы вместо копирования значений

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...