скорость параллельного исполнения в omp с std::vector и динамическим массивом
параллельное умножение матрицы на вектор выполняется во много раз быстрее с использованием динамического массива, чем с std::vector с чем это связано? последовательные версии без директив выполняются почти с одинаковой скоростью. (vs19 компилятор MSVC, собирался в релизе x64, omp в свойствах проекта прописан, 4 ядра у процессора)
#include <iostream>
#include <vector>
#include <ctime>
#include <omp.h>
void fillVector(std::vector<int>& vector)
{
for (int i = 0;i < vector.size();++i) {
vector[i] = rand() % 10;
}
}
void fillMatrix(std::vector<std::vector<int>>& matrix)
{
for (int i = 0;i < matrix.size();++i) {
for (int j = 0;j < matrix[i].size();++j) {
matrix[i][j] = rand() % 10;
}
}
}
void matmul(const std::vector<std::vector<int>>& matrix,
const std::vector<int>& vector, std::vector<int>& result)
{
int ii = matrix.size();
int jj = matrix[0].size();
#pragma omp parallel for
for (int i = 0; i < ii; ++i) {
const auto& inner{ matrix[i] };
result[i] = 0;
for (int j = 0; j < jj; ++j) {
result[i] += inner[j] * vector[j];
}
}
}
void fillVector(int* vector, const int n)
{
for (int i = 0;i < n;++i) {
vector[i] = 1 + rand() % 10;
}
}
void fillMatrix(int** matrix, const int n, const int m)
{
for (int i = 0;i < n;++i) {
for (int j = 0;j < m;++j) {
matrix[i][j] = 1 + rand() % 10;
}
}
}
void matmul(int** matrix, int* vector, int* result, const int n, const int m)
{
#pragma omp parallel for
for (int i = 0;i < n;++i) {
result[i] = 0;
for (int j = 0; j < m; ++j) {
result[i] += matrix[i][j] * vector[j];
}
}
}
int main()
{
const int n = 15000;
const int m = 15000;
std::vector<std::vector<int>> matrix(n, std::vector<int>(m));
std::vector<int> vector(m);
std::vector<int> result(n);
fillVector(vector);
fillMatrix(matrix);
clock_t startTime = clock();
matmul(matrix, vector, result);
clock_t endTime = clock();
std::cout << endTime - startTime << "msec\n";
int* vector1 = new int[m];
int** matrix1 = new int* [n];
for (int i = 0;i < n;++i) {
matrix1[i] = new int[m];
}
int* result1 = new int[n];
fillVector(vector1, m);
fillMatrix(matrix1, n, m);
startTime = clock();
matmul(matrix1, vector1, result1, n, m);
endTime = clock();
std::cout << endTime - startTime << "msec\n";
delete[] result1;
delete[] vector1;
for (int i = 0;i < n;++i) {
delete[] matrix1[i];
}
delete[] matrix1;
return 0;
}
Ответы (2 шт):
Не скажу, что тут скорости должны отличаться сильно, но работа с объектами более низкого уровня (массив по сравнению с вектором) обычно быстрее(насколько _ выясняется при выполнении определенной задачи и как написан код). Вы можете написать не оптимальный код, и выполнение отличится даже с использованием одного и того же типа. Я предпочитаю использовать std::valarray, когда нужно работать с определенным количеством элементов и, в особенности при выполнении численных расчетов. Как раз, по этому поводу я написал класс матрицы, которого представляет именно std::valarray. Операции выполняются легче и быстрее.
на самом деле скорости действительно почти не отличаются, c учетом следующего замечания одного из участников сообщества:
Вы хотите от красивого кода скорость, это мечты. Сначала используйте внутренние переменные в цикле : int sum=0;..sum+= matrix[i][j] * vector[j];..result[i]=sum; Так как чтение, запись в одно и тоже место это лишняя работа для доступа к памяти.