Назначение в std :: vectorв параллели - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть некоторый последовательный код, который умножает матричный вектор на матрицы, представленные как std::vector<std::vector<double>> и std::vector<double> соответственно:

void mat_vec_mult(const std::vector<std::vector<double>> &mat, const std::vector<double> &vec,
                  std::vector<std::vector<double>> *result, size_t beg, size_t end) {
  //  multiply a matrix by a pre-transposed column vector; returns a column vector
  for (auto i = beg; i < end; i++) {
    (*result)[i] = {std::inner_product(mat[i].begin(), mat[i].end(), vec.begin(), 0.0)};
  }
}

Я бы хотел распараллелить его, используя OpenMP, который я пытаюсь выучить. С здесь я получил следующее:

void mat_vec_mult_parallel(const std::vector<std::vector<double>> &mat, const std::vector<double> &vec,
                  std::vector<std::vector<double>> *result, size_t beg, size_t end) {
  //  multiply a matrix by a pre-transposed column vector; returns a column vector
    #pragma omp parallel
    {
        #pragma omp for nowait
          for (auto i = beg; i < end; i++) {
            (*result)[i] = {std::inner_product(mat[i].begin(), mat[i].end(), vec.begin(), 0.0)};
          }
    }
}

Этот подход не привел к ускорению; Буду признателен за помощь в выборе правильных директив OpenMP.

1 Ответ

1 голос
/ 11 апреля 2019

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

  1. Вы не активировали поддержку OpenMP на уровне вашего компилятора. Что ж, судя по комментариям, это не так, так что это может быть исключено для вас. Я все еще упоминаю об этом, поскольку это настолько распространенная ошибка, что лучше напомнить, что это необходимо.
  2. То, как вы измеряете свое время: остерегайтесь времени ЦП и истекшего времени. См. этот ответ , например, чтобы увидеть, как правильно измерить прошедшее время, поскольку это время, которое вы хотите видеть уменьшающимся.
  3. Тот факт, что ваш код ограничен памятью: обычно умножение матрицы на матрицу является типом кода, который прекрасно подходит для использования ресурсов процессора. Тем не менее, это не появляется по волшебству. Код должен быть настроен на достижение этой цели. И одним из первых методов настройки является блокирование тайлов / кеша. Цель состоит в том, чтобы максимально использовать (повторно) данные в кэш-памяти, а не извлекать их в центральную память. И, как я вижу в вашем коде, алгоритм работает с точностью до наоборот, поэтому он передает данные из памяти для обработки, полностью игнорируя потенциал повторного использования. Так что вы ограничены в памяти, и в этом случае, извините, но OpenMP не может вам сильно помочь. См. этот ответ , например, чтобы понять, почему.

Это не единственные причины, которые могут объяснить некоторую недостаточную масштабируемость, но, учитывая предоставленную вами ограниченную информацию, я думаю, что они являются наиболее вероятными виновниками.

...