Почему производительность этих умножений матриц так различается?

Я написал два класса матриц на Java просто для сравнения производительности их умножения матриц. Один класс (Mat1) хранит член double [] [] A , где row i матрицы - A [i] . Другой класс (Mat2) хранит A и T , где T ] является транспонированием A .

Допустим, у нас есть квадратная матрица M, и нам нужно произведение M.mult (M) . Назовите продукт P .

Когда M - это экземпляр Mat1, используемый алгоритм был простым:

P[i][j] += M.A[i][k] * M.A[k][j]
    for k in range(0, M.A.length)

В случае, когда M - это Mat2, я использовал:

P[i][j] += M.A[i][k] * M.T[j][k]

это тот же алгоритм потому что T [j] [k] == A [k] [j] . На матрицах 1000x1000 второй алгоритм на моей машине занимает около 1,2 секунды, а первый - не менее 25 секунд. Я ожидал, что второй будет быстрее, но не настолько. Вопрос в том, почему он настолько быстрее?

Я могу только предположить, что второй алгоритм лучше использует кеши ЦП, поскольку данные втягиваются в кеши кусками размером более 1 слова, а второй алгоритм извлекает выгоду из это путем обхода только строк, в то время как первая игнорирует данные, загруженные в кеши, сразу переходя к строке ниже (которая составляет ~ 1000 слов в памяти, поскольку массивы хранятся в порядке старших строк), ни один из данных для которых не кэшируется.

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

Итак, что это? Или есть какая-то другая причина разницы в производительности?

11
задан John Kugelman supports Monica 27 October 2010 в 00:44
поделиться