У меня включена авто-векторизация. Когда я компилирую код, я получаю следующее предупреждение:
info C5002: loop not vectorized due to reason '1203'
MSDN указывает, что
Тело цикла включает в себя несмежные обращения к массиву.
Я смотрю на эти ссылки, 1, 2, за помощь, но не повезло.
Вот мой исходный код:
for (int row = 0; row < size; ++row) {
for (int col = 0; col < size; ++col) {
float tmp = 0;
for (int i = 0; i < size; ++i) { // This loop generates the warning above
tmp += matrixA[row][i] * matrixB[i][col];
}
matrixResult[row][col] = tmp;
}
}
Любая помощь приветствуется.
Двумерные массивы хранятся в виде единого непрерывного блока памяти, поэтому двумерный массив 3х2 элемента на самом деле представляет собой 6 элементов, расположенных вплотную.
Индексирующие операторы [] просто вычисляют, к какому элементу получить доступ.
Так что здесь происходит то, что к матрице A обращаются последовательно от элемента 1 до элемента 6 (то есть A1, A2, A3, B1, B2, B3).
к матрице B, однако, обращаются «случайным образом», A1, B1, A2, B2 и т. д., которые отображаются на фактическое хранилище как элементы доступа 1, затем 4, затем 2, затем 5.
Вы не можете изменить порядок доступа к элементам matrixB, но вы можете транспонировать его так, чтобы элементы были в правильном порядке для последовательного доступа. Очевидно, что если вы сделаете это умножение только один раз, это может не стоить усилий по пересчету порядка матрицыB, но если вы выполняете это вычисление многократно, тогда усилия будут стоить того.
Если матрица A
а также B
иметь тот же порядок хранения (например, основной ряд), то вы все равно не можете векторизовать его. Так что это делает предупреждение правдоподобным.
Просто совет: если вам нужны серьезные высокопроизводительные вычисления, вам стоит отказаться от 2D-массивов. Выигрыш в кешировании намного больше, чем ускорение векторизации.
Один из способов достижения непрерывного доступа: вы можете поменять местами две внутренние петли. Вместо for row, for col, for i
у тебя есть for row, for i, for col
, Смотрите приведенный ниже код. Теперь доступ к обоим matrixResult
а также matrixB
вдоль col
так что это смежно.
for (int row = 0; row < size; ++row) {
for (int i = 0; i < size; ++i) {
int a_row_i = matrixA[row][i];
for (int col = 0; col < size; ++col) {
matrixResult[row][col] += a_row_i * matrixB[i][col];
}
}
}