Потоки OpenMP, выполняющиеся на одном ядре процессора
в настоящее время я распараллеливаю программу, используя openmp на 4-ядерном phenom2. Однако я заметил, что моя распараллеливание ничего не делает для производительности. Естественно, я предполагал, я что-то пропустил (falsesharing, сериализация через замки ...), однако я не смог найти ничего подобного. Кроме того, с ЦП казалось, что программа была выполнена только на одном ядре. Из того что я нашел 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 ядра, судя по использованию ЦП (и тот факт, что система становится очень невосприимчивой).
Итак, для моего вопроса в основном то, что именно здесь происходит. Ближе к делу: мой вывод о том, что все потоки правильно используют одно и то же ядро? Если да, то что? могли быть причины такого поведения?
4 ответов
после некоторых экспериментов я обнаружил, что проблема заключалась в том, что я запускал свою программу изнутри Eclipse IDE, которая, по-видимому, устанавливала сродство использовать только одно ядро. Я думал, что получил те же проблемы при запуске извне IDE, но повторный тест показал, что программа работает отлично, когда запускается с терминала, а не изнутри ide.
я скомпилировал вашу программу с помощью g++ 4.6 на Linux
g++ --std=c++0x -fopenmp test.cc -o test
вывод был, неудивительно:
Thread 2 on cpu 2
Thread 3 on cpu 1
910270973
Thread 1 on cpu 3
910270973
Thread 0 on cpu 0
910270973910270973
тот факт, что запущено 4 потока (если вы не установили количество потоков каким-либо образом, например, используя OMP_NUM_THREADS), должен означать, что программа может видеть 4 используемых процессора. Я не могу догадаться, почему он не использует их, но я подозреваю проблему в настройках Вашего оборудования/программного обеспечения, в какой-то переменной среды или в параметрах компилятора.
вы должны использовать #pragma omp parallel for
И да, вы правы, что не нуждаетесь в OMP_NUM_THREADS. omp_set_num_threads(4);
также должно было быть хорошо.
Если вы работаете в Windows, попробуйте это:
c:\windows\system32\cmd.exe / c start / affinity F path\to\your\program.exe
/ affinity 1 использует CPU0
/ affinity 2 использует CPU1
/ affinity 3 использует CPU0 и CPU1
/ affinity 4 использует CPU2
/ affinity F использует все 4 ядра
преобразуйте число в шестнадцатеричное и посмотрите биты справа, которые являются ядрами для использования.
вы можете проверить affinity во время работы с помощью task-manager.