hck007 Ответов: 1

Оптимизация алгоритма наивного матричного умножения


Я оптимизирую собственную версию умножения матриц и хочу оптимизировать ее с помощью OpenMP, SIMD и переупорядочивания циклов. Следующий код-это моя попытка. Мой вопрос заключается в том, как я могу изменить код, чтобы избежать дорогостоящей записи в память, которая является функцией хранения в самом внутреннем цикле.

Что я уже пробовал:

void mul_matrix(matrix *result, matrix *mat1, matrix *mat2){
    int I = mat1->rows;
    int J = mat2->cols;
    int K = mat2->rows;
    #pragma omp parallel for
    for(int i = 0; i < I; i++){
        for(int k = 0; k < K; k++){
            _m256d vA = _mm256_set1_pd(mat1->data[i * K + k]);
            for(int j = 0; j < J / 4 * 4; j += 4){
                _m256d sum = _mm256_loadu_pd(result->data + i * J + j);
                _m256d vB = _mm256_loadu_pd(mat2->data + k * J + j);
                _m256d intermediate = _mm256_mul_pd(vA, vB);
                sum = _mm256_add_pd(sum, intermediate);
                _mm256_storeu_pd(result->data + i * J + j, sum);
             }
             for(int x = J / 4 * 4; x < J; x++){
                 result->data[i * J + x] += mat1 -> data[i * K + k] * mat2 -> data[k * J + x];
             }
         }
     }
}
typedef struct matrix{
    int rows;
    int cols;
    double* data;
}matrix;

1 Ответов

Рейтинг:
6

KarstenK

убедитесь, что вы вычисляете только то, что вам нужно, извлекаете любое постоянное значение из циклов и используете const там, где это возможно.

Например, в

for(int x = J / 4 * 4; x < J; x++){
  result->data[i * J + x] += mat1 -> data[i * K + k] * mat2 -> data[k * J + x];
}
константа
int J4 = J / 4 * 4;
matrix *mr = result->data[i * J];
const matrix *m1 = mat1->data[i * K + k];
const matrix *m2 = mat2 -> data[k * J};

for(int x = J4; x < J; x++){
     mr[x] += m1 * mat2->m3[x];
}
Продвинутый-это чтобы создать ассемблерный код и посмотрите, если он показывает какие-то странные операции, такие как преобразование типов или изменение данных.