скорость параллельного исполнения в 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 шт):

Автор решения: AR Hovsepyan

Не скажу, что тут скорости должны отличаться сильно, но работа с объектами более низкого уровня (массив по сравнению с вектором) обычно быстрее(насколько _ выясняется при выполнении определенной задачи и как написан код). Вы можете написать не оптимальный код, и выполнение отличится даже с использованием одного и того же типа. Я предпочитаю использовать std::valarray, когда нужно работать с определенным количеством элементов и, в особенности при выполнении численных расчетов. Как раз, по этому поводу я написал класс матрицы, которого представляет именно std::valarray. Операции выполняются легче и быстрее.

→ Ссылка
Автор решения: Ildar

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

Вы хотите от красивого кода скорость, это мечты. Сначала используйте внутренние переменные в цикле : int sum=0;..sum+= matrix[i][j] * vector[j];..result[i]=sum; Так как чтение, запись в одно и тоже место это лишняя работа для доступа к памяти.

ссылка на вопрос и ответ

→ Ссылка