Я провел несколько экспериментов с фреймворком openmp и нашел странные результаты, я не уверен, что знаю, как объяснить.
Моя цель - создать эту огромную матрицу, а затем заполнить ее значениями. Я сделал некоторые части своего кода похожими на параллельные циклы, чтобы повысить производительность своей многопоточной среды. Я запускаю это на машине с 2-мя четырехъядерными процессорами Xeon, поэтому я могу спокойно разместить до 8 одновременных потоков.
Все работает как положено, но по какой-то причине цикл for, фактически выделяющий строки моей матрицы, имеет странную пиковую производительность при работе только с 3 потоками. С этого момента добавление еще нескольких потоков просто увеличивает продолжительность цикла. С 8 потоками на самом деле требуется больше времени, чем нужно только с одним.
Это мой параллельный цикл:
int width = 11;
int height = 39916800;
vector<vector<int> > matrix;
matrix.resize(height);
#pragma omp parallel shared(matrix,width,height) private(i) num_threads(3)
{
#pragma omp for schedule(dynamic,chunk)
for(i = 0; i < height; i++){
matrix[i].resize(width);
}
} /* End of parallel block */
Это заставило меня задуматься: есть ли известная проблема с производительностью при вызове malloc (что, я полагаю, является тем, что фактически вызывает метод resize класса векторного шаблона) в многопоточной среде? Я нашел несколько статей, в которых говорится о потере производительности при освобождении пространства кучи в многопоточном окружении, но ничего конкретного о выделении нового пространства, как в этом случае, нет.
Просто для примера приведу ниже график времени, необходимого для завершения цикла как функции от числа потоков как для цикла распределения, так и для обычного цикла, который просто читает данные из эта огромная матрица позже.
Оба раза измерялись с использованием функции gettimeofday и, по-видимому, возвращали очень похожие и точные результаты в разных экземплярах выполнения. Итак, у кого-нибудь есть хорошее объяснение?