В настоящее время я распараллеливаю программу, используя openmp на 4-ядерном Phenom2. Однако я заметил, что мое распараллеливание ничего не делает для производительности. Естественно, я предполагал, что что-то пропустил (совместное использование фальшивок, сериализация через блокировки, ...), однако я не смог найти ничего подобного. Кроме того, из-за загрузки процессора казалось, что программа была выполнена только на одном ядре. Из того, что я обнаружил, sched_getcpu()
должно дать мне идентификатор ядра, на котором запланирован поток, выполняющий вызов. Поэтому я написал следующую тестовую программу:
#include <iostream>
#include <sstream>
#include <omp.h>
#include <utmpx.h>
#include <random>
int main(){
#pragma omp parallel
{
std::default_random_engine rand;
int num = 0;
#pragma omp for
for(size_t i = 0; i < 1000000000; ++i) num += rand();
auto cpu = sched_getcpu();
std::ostringstream os;
os<<"\nThread "<<omp_get_thread_num()<<" on cpu "<<sched_getcpu()<<std::endl;
std::cout<<os.str()<<std::flush;
std::cout<<num;
}
}
На моей машине это дает следующий вывод (случайные числа будут меняться, конечно):
Thread 2 on cpu 0 num 127392776
Thread 0 on cpu 0 num 1980891664
Thread 3 on cpu 0 num 431821313
Thread 1 on cpu 0 num -1976497224
Исходя из этого, я предполагаю, что все потоки выполняются на одном ядре (с идентификатором 0). Чтобы быть более уверенным, я также попробовал подход из этого ответа . Результаты там же. Кроме того, использование #pragma omp parallel num_threads(1)
не сделало выполнение медленнее (на самом деле, немного быстрее), что подтверждает достоверность теории о том, что все потоки используют один и тот же процессор, однако тот факт, что процессор всегда отображается как 0
, вызывает у меня некоторые подозрения. , Кроме того, я проверил GOMP_CPU_AFFINITY
, который изначально не был установлен, поэтому я попытался установить его на 0 1 2 3
, что должно связывать каждый поток с ядром, отличным от того, что я понимаю. Однако это не имело значения.
Начиная с разработки на системе Windows, я использую linux в virtualbox для моей разработки. Поэтому я подумал, что, возможно, виртуальная система не может получить доступ ко всем ядрам. Однако проверка настроек virtualbox показала, что виртуальная машина должна получить все 4 ядра, а выполнение моей тестовой программы 4 раза одновременно, по-видимому, использует все 4 ядра, судя по использованию ЦП (и тому факту, что система очень не отвечает) ,
Итак, мой вопрос в основном о том, что именно здесь происходит. Ближе к делу:
Мой вывод, что все потоки правильно используют одно и то же ядро? Если это так, что может быть причиной такого поведения?