2017-05-06 5 views
1

Ich habe ein Problem mit memcpy, das ich nicht zu verstehen scheinen. Ich benutze memcpy auf einem Thread und es ist 3-4 mal langsamer im Vergleich zu der Zeit, die ich bekomme, wenn ich es von der Hauptleitung aus führe. In beiden Fällen habe ich 2 Threads, von denen einer nur wartet und einer memcpy aufruft. Können Sie mir eine mögliche Erklärung dafür geben? Ich benutze eine 4-Core-Intel-Maschine mit Hyperthreading.memcpy langsam beim Aufruf in Thread

#include <stdio.h> 
#include <unistd.h> 
#include <sys/time.h> 
#include <string.h> 
#include <pthread.h> 
#include <algorithm> 
#define MILLION 1000000 

#define START_TIMER(timer) {   \ 
    gettimeofday(&(timer), NULL);   \ 
} 

#define STOP_TIMER(timer) {   \ 
    gettimeofday(&(timer), NULL);   \ 
} 

#define TIME_DIFF(timer1, timer2, total) {  \ 
    long long sec_diff = 0;   \ 
    long long usec_diff = 0;   \ 
    sec_diff = (timer2).tv_sec - (timer1).tv_sec;  \ 
    usec_diff = (timer2).tv_usec - (timer1).tv_usec; \ 
    (total)+= (sec_diff * MILLION) + usec_diff;  \ 
} 
void copy(){ 
    struct timeval start, stop; 
    long long total=0; 
    char buff[1024*1024]; 
    for(int i =0;i<100;i++){ 

    char* temp = new char[1024*1024]; 
    START_TIMER(start); 
    std::copy(buff,buff+1024*1024,temp); 
    STOP_TIMER(stop); 
    TIME_DIFF(start,stop,total); 
    delete temp; 
    } 
    printf("%lld\n",total/100); 
} 
void* mem(void* args){ 
    copy(); 
    pthread_exit(NULL); 
} 

void * nothing(void *args){ 
    pthread_exit(NULL); 

} 
pthread_t thread; 
int main(int argc,char* argv[]){ 
    if(atoi(argv[1])==0){ 
     pthread_create(&thread,NULL,nothing,NULL); 
     pthread_join(thread,NULL); 
     copy(); 
    } 
    else{ 

     pthread_create(&thread,NULL,mem,NULL); 
     pthread_join(thread,NULL); 
    } 
} 

Vielen Dank für Ihre Zeit. Ich hoffe es ist nicht zu dumm.

+1

Was passiert, wenn Sie 'buff' vor Ihrer' i' Schleife initialisieren? – 1201ProgramAlarm

+0

Bitte teilen Sie den Code, wo Sie die Kopierfunktion von Haupt und von den Threads aufrufen. Damit wir versuchen können, das Problem zu reproduzieren. – Sush

+0

Was passiert, wenn Sie die copy() in main() über dem Thread create verschieben, dh zuerst die Hauptthread-Kopie ausführen? – ThingyWotsit

Antwort

0

Zuerst konnte ich Ihren Code nicht ausführen, wenn es den Aufruf an copy() passiert der Thread (1 als Argument übergeben). pthread_create weist eine kleine Stapelgröße zu und deklariert, dass das 1-MB-Array buff einen Segmentierungsfehler verursacht hat.

verändern ich den Code einen größeren Stapel für den Thread zuzuordnen:

int main(int argc,char* argv[]){ 
    if(atoi(argv[1])==0){ 
     pthread_create(&thread,NULL,nothing,NULL); 
     pthread_join(thread,NULL); 
     copy(); 
    } 
    else{ 
     pthread_attr_t thread_attr; 
     pthread_attr_init(&thread_attr); 
     pthread_attr_setstacksize(&thread_attr , 20*1024*1024); 
     pthread_create(&thread, &thread_attr,mem,NULL); 
     pthread_join(thread,NULL); 
    } 
} 

Dies funktioniert, und es gibt keinen Unterschied in Runtimes zwischen dem Kopieren auf beiden Thread auf meinem Rechner.

Ihr OS kann jedoch zu Heapkonflikten führen. Jedes Mal, wenn es Speicher reservieren muss, muss es die Kontrolle über einen "Mutex" (irgendeiner Art, wahrscheinlich ein Spin_lock) erlangen, um sicherzustellen, dass kein anderer Thread den Heap belegt/freigibt. Dies würde die Verzögerungen verursachen, die Sie erfahren.

+1

Der Code funktioniert für mich wie es war und ich bekomme etwa 100 usecs vs 300+ usecs. Ich habe Ihren Code auch versucht, aber ich habe immer noch das gleiche Problem. Danke für deine Zeit, ich weiß es zu schätzen. Ich habe gerade Ihre Bearbeitung über das Betriebssystem und den Mutex auf dem Heap gesehen. Sollte dies nicht zu Problemen in beiden Fällen führen? Warum sollte es nur so offensichtlich auf einem von ihnen sein? – Pol

+0

Haben Sie mein Update über Heap-Contention gelesen? Ich denke, unsere Architekturen handhaben die Haufen unterschiedlich. –

+0

(Ich laufe auf einem I7 mit 4 Kernen und Hyperthreading, OS ist Mac OS 10.11 btw) –

0

Es scheint einen Unterschied in der Anzahl der Threads für den Prozess zu geben, wenn die Funktion 'copy' aufgerufen wird. Wenn es vom Hauptthread aufgerufen wird, ist der Thread "nothing" bereits beendet, so dass es effektiv nur einen Thread für den Prozess gibt. Aber während es aus dem 'mem'-Thread aufgerufen wird, gibt es effektiv zwei Threads im System. Dies kann einen Unterschied machen, wenn das System geladen wird oder Konflikte zwischen den Threads des Prozesses auftreten. Dieser Zeitunterschied ist möglicherweise nicht vorhanden, wenn er auf einem anderen Computer oder auf einem weniger ausgelasteten Computer ausgeführt wird. Diese Theorie kann überprüft werden, indem der Code so geändert wird, dass Sie im Nothing-Thread warten und ihn erst nach dem Aufruf der Kopierfunktion abbrechen.

+0

Sie haben Recht, die Kopie soll vor dem Beitritt sein. Ich habe das behoben, aber ich habe immer noch die gleichen Ergebnisse. Danke für deine Korrektur. – Pol