2012-02-15 12 views
5

La mia CPU è un Core i3 330M con 2 core e 4 thread. Quando eseguo il comando cat /proc/cpuinfo nel mio terminale, è come se avessi 4 CPUS. Quando uso la funzione OpenMPOpenMP e core/thread

Ora ho una classe di vettore C++ standard, intendo una classe di array doppio di dimensioni fisse che non utilizza modelli di espressione. Ho attentamente parallelizzato tutti i metodi della mia classe e ottengo l'accelerazione "attesa".

La domanda è: posso immaginare l'accelerazione prevista in un caso così semplice? Ad esempio, se aggiungo due vettori senza cicli for paralleli, ottengo un po 'di tempo (usando il comando shell time). Ora se uso OpenMP, dovrei ottenere un tempo diviso per 2 o 4, in base al numero di core/thread? Sottolineo che sto solo chiedendo questo particolare problema semplice, in cui non c'è alcuna interdipendenza nei dati e tutto è lineare (aggiunta vettoriale).

Ecco il codice:

Vector Vector::operator+(const Vector& rhs) const 
{ 
    assert(m_size == rhs.m_size); 
    Vector result(m_size); 
    #pragma omp parallel for schedule(static) 
    for (unsigned int i = 0; i < m_size; i++) 
      result.m_data[i] = m_data[i]+rhs.m_data[i]; 

    return result; 
} 

ho già letto questo post: OpenMP thread mapping to physical cores.

Spero che qualcuno mi spieghi di più su come OpenMP può portare a termine il lavoro in questo semplice caso. Devo dire che sono un principiante nel calcolo parallelo.

Grazie!

risposta

3

MODIFICA: Ora che è stato aggiunto del codice.

In questo particolare esempio, c'è molto poco calcolo e un sacco di accesso alla memoria. Quindi le prestazioni dipenderanno in gran parte da:

  • La dimensione del vettore.
  • Come lo cronometrate. (si dispone di un ciclo esterno per scopi di temporizzazione)
  • Se i dati sono già nella cache.

Per dimensioni vettoriali maggiori, è probabile che le prestazioni siano limitate dalla larghezza di banda della memoria. In tal caso, il parallelismo non aiuterà molto. Per le taglie più piccole, l'overhead del threading domina. Se ottieni l'accelerazione "attesa", probabilmente sei in una posizione intermedia in cui il risultato è ottimale.

Rifiuto di fornire numeri complessi perché in generale, le prestazioni di "indovinare", in particolare nelle applicazioni multi-thread, sono una causa persa a meno che non si disponga di una conoscenza preliminare o di una conoscenza approfondita del programma e del sistema su cui è in esecuzione.

Proprio come un semplice esempio tratto dalla mia risposta qui: How to get 100% CPU usage from a C program

Su un Core i7 920 @ 3.5 GHz (4 core, 8 thread):

Se corro con 4 fili, il risultato è:

This machine calculated all 78498 prime numbers under 1000000 in 39.3498 seconds 

Se corro con 4 fili ed esplicitamente (utilizzando Task Manager) pin i fili su 4 core fisici distinti, il risultato è:

This machine calculated all 78498 prime numbers under 1000000 in 30.4429 seconds 

Questo dimostra quanto sia imprevedibile persino un'applicazione parallela molto semplice e imbarazzante. Le applicazioni che coinvolgono l'utilizzo della memoria pesante e la sincronizzazione diventano molto più brutte ...

1

Per aggiungere alla risposta Mysticals. Il tuo problema è puramente larghezza di banda di memoria limitata. Dai uno sguardo allo STREAM benchmark. Eseguilo sul tuo computer in casi singoli e multi-thread e guarda i risultati della Triade - questo è il tuo caso (beh, quasi, dal momento che il vettore di output è allo stesso tempo uno dei tuoi vettori di input). Calcola la quantità di dati che ti muovi e saprai esattamente quali prestazioni aspettarti.

Il multithreading funziona per questo problema? Sì. È raro che un singolo core della CPU possa saturare l'intera larghezza di banda della memoria del sistema. I computer moderni bilanciano la larghezza di banda della memoria disponibile con il numero di core disponibili. Dalla mia esperienza avrete bisogno di circa la metà dei core per saturare la larghezza di banda della memoria con una semplice operazione di memcopy. Potrebbe volerci qualche altro se fai qualche calcolo lungo il percorso.

Si noti che sui sistemi NUMA è necessario associare i thread ai core della CPU e utilizzare l'allocazione della memoria locale per ottenere risultati ottimali. Questo perché su tali sistemi ogni CPU ha la sua memoria locale, a cui l'accesso è il più veloce. È comunque possibile accedere all'intera memoria del sistema come avviene per gli SMP tradizionali, ma ciò comporta costi di comunicazione: le CPU devono scambiarsi esplicitamente i dati. Legare i thread alle CPU e utilizzare l'allocazione locale è estremamente importante. Non riuscendo a fare ciò uccide la scalabilità. Controlla libnuma se vuoi farlo su Linux.