Jestem w trakcie równoległego programowania za pomocą OpenMP na 4-rdzeniowym phenom2. Zauważyłem jednak, że moja równoległość nic nie robi dla wydajności. Naturalnie założyłem, że coś przeoczyłem (przeskakiwanie, serializacja przez blokady, ...), jednak nie mogłem znaleźć czegoś takiego. Co więcej, z użycia CPU wydawało się, że program został wykonany tylko na jednym rdzeniu. Z tego, co znalazłem sched_getcpu()
powinien dać mi identyfikator rdzenia wątku wykonywania połączenia jest obecnie zaplanowane na. Więc napisałem następujący program testowy:Wątki OpenMP wykonywane na tym samym rdzeniu procesora
#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;
}
}
Na moim komputerze to daje następujący wynik (losowe numery będą się różnić od kursu):
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
Od tego zakładam, że wszystkie wątki wykonać na ten sam rdzeń (ten z identyfikatorem 0). Aby być bardziej pewnym spróbowałem także podejścia z this answer. Wyniki są takie same. Dodatkowo użycie #pragma omp parallel num_threads(1)
nie spowolniło wykonania (nieco szybciej w rzeczywistości), dodając wiarygodności teorii, że wszystkie wątki używają tego samego procesora, jednak fakt, że procesor jest zawsze wyświetlany jako 0
sprawia, że jestem podejrzany. Dodatkowo sprawdziłem GOMP_CPU_AFFINITY
, który początkowo nie był ustawiony, więc próbowałem ustawić go na 0 1 2 3
, który powinien związać każdy wątek z innym rdzeniem niż to, co rozumiem. Jednak to nie miało znaczenia.
Odkąd pracuję w systemie Windows, używam Linuksa w Virtualboksie do mojego rozwoju. Więc myślę, że może system wirtualny nie może uzyskać dostępu do wszystkich rdzeni. Jednak sprawdzanie ustawień wirtualnej skrzynki pokazywało, że wirtualna maszyna powinna pobrać wszystkie 4 rdzenie i wykonując mój testowy program 4 razy w tym samym czasie wydaje się używać wszystkich 4 rdzeni, biorąc pod uwagę wykorzystanie procesora (i fakt, że system bardzo przestał reagować) .
Moje pytanie brzmi: co właściwie się tutaj dzieje? Bardziej do rzeczy: Czy moje odliczenie, że wszystkie wątki używają tego samego rdzenia poprawnie? Jeśli tak, jakie mogą być tego powody?
Czy istnieje wspólny błąd, czy ustawiłeś zmienną środowiskową OMP_NUM_THREADS = 4? – pyCthon
@pyCthon: 'OMP_NUM_THREADS' nie wydaje się być ustawiony, jednak ponieważ openmp tworzy 4 wątki, nie sądzę, bym musiał. – Grizzly
Dziwne myślę, że może to być coś z maszyną wirtualną próbowałem tego samego kodu nawet zainstalowany utmpx.h i wydawało się, że działa dobrze na 8 i 16 podstawowych maszynach – pyCthon