2014-02-14 3 views
32

Учитывая матрицу m = [10i+j for i=1:3, j=1:4], я могу перебрать ее строк, нарезая матрицу:Каков рекомендуемый способ перебора матрицы по строкам?

for i=1:size(m,1) 
    print(m[i,:]) 
end 

Это единственная возможность? Это рекомендуемый способ?

А как насчет понятий? Разрезает единственную возможность итерации по строкам матрицы?

[ sum(m[i,:]) for i=1:size(m,1) ] 
+4

mapslices? 'mapslices (sum, m, 2)' делает последнее – jverzani

+0

@jverzani mapslices выполняет эту работу, хотя в некоторых случаях для этого потребуется определить анонимную функцию. Спасибо за предложения. – Nico

ответ

38

Решение, которое вы указали сами, а также mapslices, оба работают нормально. Но если «рекомендуется», что вы действительно имеете в виду, это «высокопроизводительный», тогда лучший ответ: не перебирайте строки.

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

Как отмечалось в excellent blog post, если вы хотите суммировать по строкам, то лучше всего, чтобы сделать что-то вроде этого:

msum = zeros(eltype(m), size(m, 1)) 
for j = 1:size(m,2) 
    for i = 1:size(m,1) 
     msum[i] += m[i,j] 
    end 
end 

Мы траверс как m и msum в своем родном порядке хранения, так что каждый время, в которое мы загружаем линию кэша, мы используем все значения, что дает коэффициент попадания в кэш 1. Вы можете наивно полагать, что лучше пройти его в порядке строк и скопировать результат в переменную , но на любой современной машине кеш промах намного дороже, чем поиск msum[i].

Многие внутренние алгоритмы Юлии, которые принимают параметр region, например sum(m, 2), обрабатывают это для вас.

+1

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

+0

Сообщение блога, с которым вы связались, больше не существует. Вместо этого см. Http://docs.julialang.org/en/release-0.4/manual/performance-tips/#access-arrays-in-memory-order-along-columns. – aventurin

+2

404 похоже из-за задней косой черты. Этот URL-адрес работает: http://julialang.org/blog/2013/09/fast-numeric –

2

Согласно моим опытам, явные итерации намного быстрее, чем осознания.

Итерация по колонкам также является хорошим советом.

Кроме того, вы можете использовать новые макросы @simd и @inbounds для дальнейшего ускорения.

Смежные вопросы