Медленное (повторное) умножение матриц в Юлии 1.0 - PullRequest
0 голосов
/ 17 сентября 2018

Следующая часть в моем коде Джулии убивает все мое исполнение:

        for j = 1:size(phi,3)
            for i = 1:size(phi,2)
                    phi[:,i,j] += dt*convolutionmagnitude*
                                    weightMatrix*phi[:,i,j]                     
            end
        end 

Т.е. phi - это три тензор, и для каждого i, j мы хотим обновить первое измерениепроизведением матрицы на вектор (умноженное на несколько скаляров).weightMatrix - это матрица размером size(phi,1) на size(phi,1) (которая может быть редкой в ​​будущем).Все происходит с floats.

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

1 Ответ

0 голосов
/ 17 сентября 2018
  • Срезы (phi[:,i,j]) в правой части назначений всегда выделяются.Как вы сказали, вы можете использовать представления (которые еще не полностью распределены (пока)), что должно ускорить процесс.Ниже я использую макрос @views, который заменяет все срезы представлениями.

  • Ваша операция += также выделяет.a += b в основном a = a + b, который выделит массив для a+b, а затем назначит ему.Это не на месте.Чтобы сделать его на месте, вам нужно добавить точку: a .+= b.

  • После того, как ваш код запущен, вы можете добавить @inbounds, чтобы отключить привязанные проверки при доступе к частям массивов..

В общем, попробуйте следующее:

    @inbounds @views for j = 1:size(phi,3)
        for i = 1:size(phi,2)
                phi[:,i,j] .+= dt .* convolutionmagnitude .* weightMatrix * phi[:,i,j]                     
        end
    end

Обратите внимание, что это все равно будет выделено, так как создает промежуточный вектор для weightMatrix * phi[:,i,j].Вы не можете поставить точку здесь, поскольку это будет означать поэлементное умножение, а не умножение матрицы на вектор.Однако вы можете повторно использовать предварительно выделенный фрагмент памяти, используя mul! (при условии, что Юлия здесь> 0,7):

    using LinearAlgebra # get mul!

    tmp = similar(phi[:,1,1])
    @inbounds @views for j = 1:size(phi,3)
        for i = 1:size(phi,2)
                mul!(tmp, weightMatrix, phi[:,i,j])
                phi[:,i,j] .+= dt .* convolutionmagnitude .* tmp                   
        end
    end

Наконец, позвольте мне дать вам несколько хороших прочтений по этому вопросу:

Отказ от ответственности: я не проверял ничего из этого, но просто записал это в текстовом редакторездесь, так что он может содержать тривиальные опечатки или аналогичные.Тем не менее, я надеюсь, что это демонстрирует некоторые проблемы и помогает!

...