Domanda

Quindi mi rendo conto che questa domanda sembra stupida (e sì, sto usando un dual core), ma ho provato due librerie diverse (Grand Central Dispatch e OpenMP) e quando utilizzo clock() per cronometrare il codice con e senza le righe che compongono è parallelo, la velocità è la stessa.(per la cronaca entrambi usavano la propria forma di parallelo).Riferiscono di essere eseguiti su thread diversi, ma forse sono in esecuzione sullo stesso core?C'è un modo per controllare?(Entrambe le librerie sono per C, mi sento a disagio nei livelli inferiori.) Questo è davvero strano.Qualche idea?

È stato utile?

Soluzione

MODIFICARE:Aggiunti dettagli per Grand Central Dispatch in risposta al commento del PO.

Sebbene le altre risposte qui siano utili in generale, la risposta specifica alla tua domanda è che non dovresti usarle clock() per confrontare i tempi. clock() misura il tempo della CPU che viene sommato tra i thread.Quando dividi un lavoro tra i core, utilizza almeno la stessa quantità di tempo della CPU (di solito un po' di più a causa del sovraccarico del threading).Cerca clock() acceso Questo pagina, per trovare "Se il processo è multi-thread, viene aggiunto il tempo della CPU consumato da tutti i singoli thread del processo."

È solo che il lavoro è suddiviso tra i thread, quindi il tempo complessivo che devi aspettare è inferiore.Dovresti utilizzare l'ora a muro (l'ora su un orologio da parete).OpenMP fornisce una routine omp_get_wtime() per farlo.Prendiamo come esempio la seguente routine:

#include <omp.h>
#include <time.h>
#include <math.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    int i, nthreads;
    clock_t clock_timer;
    double wall_timer;
    for (nthreads = 1; nthreads <=8; nthreads++) {
        clock_timer = clock();
        wall_timer = omp_get_wtime();
        #pragma omp parallel for private(i) num_threads(nthreads)
        for (i = 0; i < 100000000; i++) cos(i);
        printf("%d threads: time on clock() = %.3f, on wall = %.3f\n", \
            nthreads, \
            (double) (clock() - clock_timer) / CLOCKS_PER_SEC, \
            omp_get_wtime() - wall_timer);
    }
}

I risultati sono:

1 threads: time on clock() = 0.258, on wall = 0.258
2 threads: time on clock() = 0.256, on wall = 0.129
3 threads: time on clock() = 0.255, on wall = 0.086
4 threads: time on clock() = 0.257, on wall = 0.065
5 threads: time on clock() = 0.255, on wall = 0.051
6 threads: time on clock() = 0.257, on wall = 0.044
7 threads: time on clock() = 0.255, on wall = 0.037
8 threads: time on clock() = 0.256, on wall = 0.033

Puoi vedere che il clock() il tempo non cambia moltoOttengo 0,254 senza il pragma, quindi è un po' più lento usare openMP con un thread che non usare affatto openMP, ma il tempo trascorso diminuisce con ogni thread.

Il miglioramento non sarà sempre così significativo a causa, ad esempio, di parti del calcolo che non sono parallele (vedi Legge_di Amdahl) o thread diversi in conflitto per la stessa memoria.

MODIFICARE:Per Grand Central Dispatch, il Riferimento GCD afferma, che GCD utilizza gettimeofday per il tempo al muro.Quindi, creo una nuova Cocoa App e in applicationDidFinishLaunching Metto:

struct timeval t1,t2;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int iterations = 1; iterations <= 8; iterations++) {
    int stride = 1e8/iterations;
    gettimeofday(&t1,0);
    dispatch_apply(iterations, queue, ^(size_t i) { 
        for (int j = 0; j < stride; j++) cos(j); 
    });
    gettimeofday(&t2,0);
    NSLog(@"%d iterations: on wall = %.3f\n",iterations, \
                t2.tv_sec+t2.tv_usec/1e6-(t1.tv_sec+t1.tv_usec/1e6));
}

e ottengo i seguenti risultati sulla console:

2010-03-10 17:33:43.022 GCDClock[39741:a0f] 1 iterations: on wall = 0.254
2010-03-10 17:33:43.151 GCDClock[39741:a0f] 2 iterations: on wall = 0.127
2010-03-10 17:33:43.236 GCDClock[39741:a0f] 3 iterations: on wall = 0.085
2010-03-10 17:33:43.301 GCDClock[39741:a0f] 4 iterations: on wall = 0.064
2010-03-10 17:33:43.352 GCDClock[39741:a0f] 5 iterations: on wall = 0.051
2010-03-10 17:33:43.395 GCDClock[39741:a0f] 6 iterations: on wall = 0.043
2010-03-10 17:33:43.433 GCDClock[39741:a0f] 7 iterations: on wall = 0.038
2010-03-10 17:33:43.468 GCDClock[39741:a0f] 8 iterations: on wall = 0.034

che è più o meno lo stesso di cui stavo parlando sopra.

Questo è un esempio molto artificioso.In effetti, devi essere sicuro di mantenere l'ottimizzazione su -O0, altrimenti il ​​compilatore si renderà conto che non conserviamo nessuno dei calcoli e non eseguiamo affatto il ciclo.Inoltre, il numero intero che sto prendendo il cos of è diverso nei due esempi, ma ciò non influisce troppo sui risultati.Vedi il STRIDE nella manpage di dispatch_apply su come farlo correttamente e perché iterations è ampiamente paragonabile a num_threads in questo caso.

MODIFICARE:Noto che la risposta di Jacob include

Uso la funzione omp_get_thread_num () all'interno del mio ciclo parallelato per stampare su quale core sta lavorando ...In questo modo puoi essere sicuro che sia in esecuzione su entrambi i core.

che non è corretto (è stato parzialmente corretto da una modifica).Utilizzando omp_get_thread_num() è davvero un buon modo per garantire che il tuo codice sia multithread, ma non mostra "su quale core sta lavorando", solo su quale thread.Ad esempio, il seguente codice:

#include <omp.h>
#include <stdio.h>

int main() {
    int i;
    #pragma omp parallel for private(i) num_threads(50)
    for (i = 0; i < 50; i++) printf("%d\n", omp_get_thread_num());
}

stampa che sta utilizzando i thread da 0 a 49, ma questo non mostra su quale core sta lavorando, poiché ho solo otto core.Osservando Activity Monitor (l'OP menziona GCD, quindi deve essere su un Mac: vai Window/CPU Usage), puoi vedere i lavori passare da un core all'altro, quindi core != thread.

Altri suggerimenti

Molto probabilmente il tempo di esecuzione non è vincolata da tali cicli si parallelized.

Il mio suggerimento è che si profilo il codice per vedere cosa sta prendendo la maggior parte del tempo. La maggior parte ingegneri vi diranno che si dovrebbe fare prima di fare qualcosa di drastico per ottimizzare le cose.

E 'difficile da indovinare, senza alcun dettaglio. Forse l'applicazione non è nemmeno CPU. Hai visto il carico della CPU, mentre il codice è in esecuzione? Lo ha colpito al 100% su almeno un core?

La tua domanda manca alcuni dettagli molto importanti come quello che la natura della vostra applicazione è, quale parte di esso stai cercando di migliorare, profilatura risultati (se presente), ecc ...

Dopo aver detto che si dovrebbe ricordare diversi punti critici quando si avvicina uno sforzo di miglioramento delle prestazioni:

  • Gli sforzi deve sempre concentrarsi sulle zone di codice che hanno dimostrato, di profilatura , di essere l'inefficiente
  • parallelizzazione del codice CPU bound sarà quasi mai migliorare le prestazioni (su una singola macchina core). Sarete perdere tempo prezioso per cambi di contesto inutili e guadagnando non . Si può facilmente peggiorare le prestazioni in questo modo.
  • Anche se si sta parallelizzazione del codice della CPU bound su una macchina multicore, è necessario ricordare che non hai mai alcuna garanzia di esecuzione parallela.

Assicurarsi che non sta andando contro questi punti, perché un'ipotesi (salvo eventuali dettagli aggiuntivi) dirà che è esattamente quello che stai facendo.

Se si utilizza un sacco di memoria all'interno del ciclo, che potrebbe impedirgli di essere più veloce. Inoltre si poteva guardare in libreria pthread, per gestire manualmente threading.

Io uso la funzione omp_get_thread_num() nel mio ciclo parallelizzato stampare cui nucleo si sta lavorando su se non si specifica num_threads . Per es.,

printf("Computing bla %d on core %d/%d ...\n",i+1,omp_get_thread_num()+1,omp_get_max_threads());

È possibile che questo funzionerà per questo pragma     #pragma omp parallela per impostazione predefinita (nessuno) in comune (a, b, c)

In questo modo si può essere sicuri che è in esecuzione su entrambi i core in quanto solo 2 le discussioni verrà creato.

A proposito, è abilitato OpenMP quando si sta compilando? In Visual Studio è necessario abilitare nel Pagine delle proprietà di , C++ -> Language e impostare OpenMP Support a Yes

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top