Я хочу умножить две матрицы, один раз, используя алгоритм прямой прямой связи:
template <typename T>
void multiplicate_straight(T ** A, T ** B, T ** C, int sizeX)
{
T ** D = AllocateDynamicArray2D<T>(sizeX, sizeX);
transpose_matrix(B, D,sizeX);
for(int i = 0; i < sizeX; i++)
{
for(int j = 0; j < sizeX; j++)
{
for(int g = 0; g < sizeX; g++)
{
C[i][j] += A[i][g]*D[j][g];
}
}
}
FreeDynamicArray2D<T>(D);
}
и один раз с помощью SSE-функций. Для этого я создал две функции:
template <typename T>
void SSE_vectormult(T * A, T * B, int size)
{
__m128d a;
__m128d b;
__m128d c;
#ifdef linux
double A2[2], B2[2], C[2] __attribute__ ((aligned(16)));
#endif
#ifdef _WIN32
__declspec(align(16)) double A2[2], B2[2], C[2];
#endif
for(int i = 0; i < size; i+=2)
{
//std::cout << "In SSE_vectormult: i is: " << i << '\n';
A2[0] = A[i];
B2[0] = B[i];
A2[1] = A[i+1];
B2[1] = B[i+1];
//std::cout << "Values from A and B written to A2 and B2\n";
a = _mm_load_pd(A2);
b = _mm_load_pd(B2);
//std::cout << "Values converted to a and b\n";
c = _mm_mul_pd(a,b);
_mm_store_pd(C, c);
A[i] = C[0];
A[i+1] = C[1];
};
}
и
template <typename T>
void multiplicate_SSE(T ** A, T ** B, T ** C, int sizeX)
{
// std::cout << "Entered SSE-Function\n";
T ** D = AllocateDynamicArray2D<T>(sizeX, sizeX);
T * tmp = AllocateDynamicArray1D<T>(sizeX);
T * tmp2 = AllocateDynamicArray1D<T>(sizeX);
//std::cout << "Matrices allocated\n";
transpose_matrix<T>(B, D,sizeX);
//std::cout << "Matrix B transposed\n";
for(int i = 0; i < sizeX; i++)
{
for(int j = 0; j < sizeX; j++)
{
extract_row<T>(A,tmp, i, sizeX);
// std::cout << "Row from A extracted\n";
//print_vector(tmp, sizeX);
extract_row<T>(D, tmp2, j, sizeX);
// std::cout << "Row from D extracted\n";
//print_vector(tmp2, sizeX);
SSE_vectormult<T>(tmp, tmp2, sizeX);
// std::cout << "Vectors multiplicated\n";
//print_vector(tmp, sizeX);
C[i][j] = add_vector(tmp, sizeX);
// std::cout << "Written value to C\n";
// std::cout << "j is " << j << " and i is " << i << '\n';
}
}
// std::cout << "Loop finished\n";
FreeDynamicArray2D<T>(D);
//std::cout << "Freed D\n";
//FreeDynamicArray1D<T>(tmp);????
// std::cout << "Freed tmp\n";
FreeDynamicArray1D<T>(tmp2);
// std::cout << "Everything freed, returning\n";
}
Но потом у меня возникает несколько проблем: с одной стороны, когда я хочу освободить tmp-массив в multipicate_SSE(), помеченном несколькими вопросительными знаками, я получаю сообщение об ошибке "_BLOCK_TYPE_IS_VALID". Я подумал о возможности освобождения одного и того же пространства дважды, поэтому я раскоментировал это (но, как я полагаю, я получаю утечку памяти через это?). Теперь, когда я сравниваю производительность обеих функций с одинаковыми матрицами, функция SSE нуждается примерно в четыре раза дольше для двух матриц 1024x1024, чем метод прямой перемотки.
Как я могу переписать мою SSE-функцию, чтобы получить лучшую производительность (раньше я никогда не работал с SSE), и как я могу исправить утечку памяти?
Спасибо!