Потоки OpenMP, выполняющиеся на том же ядре процессора - PullRequest
7 голосов
/ 21 февраля 2012

В настоящее время я распараллеливаю программу, используя 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 ядра, судя по использованию ЦП (и тому факту, что система очень не отвечает) ,

Итак, мой вопрос в основном о том, что именно здесь происходит. Ближе к делу: Мой вывод, что все потоки правильно используют одно и то же ядро? Если это так, что может быть причиной такого поведения?

Ответы [ 4 ]

6 голосов
/ 02 июля 2012

После некоторых экспериментов я обнаружил, что проблема заключалась в том, что я запускал свою программу из среды IDE затмения, которая, по-видимому, устанавливала сходство для использования только одного ядра. Я думал, что у меня возникли те же проблемы при запуске из-за пределов IDE, но повторный тест показал, что программа работает нормально, когда запускается из терминала, а не изнутри ide.

2 голосов
/ 22 мая 2012

Я скомпилировал вашу программу, используя 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 используемых ЦП.Я не могу догадаться, почему он их не использует, но я подозреваю, что проблема в настройках вашего аппаратного / программного обеспечения, в некоторой переменной среды или в параметрах компилятора.

0 голосов
/ 21 февраля 2012

если вы работаете в Windows, попробуйте это:

c: \ windows \ system32 \ cmd.exe / C запуск / сходство F path \ to \ your \ program.exe

/ affinity 1 использует CPU0

/ affinity 2 использует CPU1

/ affinity 3 использует CPU0 и CPU1

/ affinity 4 использует CPU2

/ affinity F использует все 4 ядра

Преобразуйте число в шестнадцатеричное и посмотрите биты справа, которые являются ядрами, которые будут использоваться.

вы можете проверить соответствие во время его работы с помощью диспетчера задач.

0 голосов
/ 21 февраля 2012

Вы должны использовать #pragma omp parallel for
И да, вы правы в том, что вам не нужен OMP_NUM_THREADS.omp_set_num_threads(4); тоже должно было быть хорошо.

...