Потоки 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.