Простое и быстрое матрично-векторное умножение в C / Stack Overflow

Мне нужно частое использование matrix_vector_mult() которая умножает матрицу на вектор, а ниже — ее реализация.

Вопрос: Есть ли простой способ сделать это значительно, по крайней мере, вдвое быстрее?

Примечания: 1) Размер матрицы составляет около 300х50. Не меняется во время
запустить. 2) Он должен работать как на Windows, так и на Linux.

double vectors_dot_prod(const double *x, const double *y, int n)
{
double res = 0.0;
int i;
for (i = 0; i < n; i++)
{
res += x[i] * y[i];
}
return res;
}

void matrix_vector_mult(const double **mat, const double *vec, double *result, int rows, int cols)
{ // in matrix form: result = mat * vec;
int i;
for (i = 0; i < rows; i++)
{
result[i] = vectors_dot_prod(mat[i], vec, cols);
}
}

16

Решение

Это то, что теоретически хороший компилятор должен делать сам по себе, однако я попробовал с моей системой (g ++ 4.6.3) и получил примерно вдвое большую скорость на матрице 300×50, вручную развернув 4 умножения (около 18us на матрицу вместо 34us за матрицу):

double vectors_dot_prod2(const double *x, const double *y, int n)
{
double res = 0.0;
int i = 0;
for (; i <= n-4; i+=4)
{
res += (x[i] * y[i] +
x[i+1] * y[i+1] +
x[i+2] * y[i+2] +
x[i+3] * y[i+3]);
}
for (; i < n; i++)
{
res += x[i] * y[i];
}
return res;
}

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

19

Другие решения

Как говорит Женя, просто используйте хорошую BLAS или матричную математическую библиотеку.

Если по какой-то причине вы не можете этого сделать, посмотрите, может ли ваш компилятор развернуть и / или векторизовать ваши циклы; убедиться строки а также смещ_по_столбцам Обе константы на сайте вызова могут помочь, при условии, что опубликованные вами функции доступны для встраивания

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

4

Если размер постоянен и известен заранее, передайте его как переменную прекомпилятора, что позволит компилятору оптимизировать работу более полно.

0