2017-05-06 17 views
1

私は理解していないmemcpyに問題があります。私はスレッド上でmemcpyを使用し、メインから実行するときに比べて3-4倍遅くなります。どちらの場合も、私は2つのスレッドがただ待っていて、もう1つはmemcpyを呼び出しています。あなたはこれについて何か可能な説明をしてくれますか?私はハイパースレッディング付きの4コアIntelマシンを使用しています。スレッドで呼び出されたときにmemcpyが遅い

#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); 
    } 
} 

ありがとうございます。私はそれがあまりにも愚かでないことを願っています。

+1

あなたの 'i'ループの前に' buff'を初期化するとどうなりますか? – 1201ProgramAlarm

+0

メインから、そしてスレッドからコピー機能を呼び出すコードを共有してください。問題を再現しようとすることができるように。 – Sush

+0

main()の中のcopy()をスレッド作成の上に移動した場合、つまりメインスレッドのコピーを先に実行するとどうなりますか? – ThingyWotsit

答えて

0

最初に、copy()への呼び出しがスレッド(引数として1を渡す)を実行したときに、コードを実行することができませんでした。 pthread_createは小さなスタックサイズを割り当て、1MBの配列buffがセグメンテーション違反を引き起こしていると宣言しました。

私はスレッドの大きなスタックを割り当てるようにコードを変更:

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); 
    } 
} 

これは動作し、私のマシン上のいずれかのスレッド上のコピーの間に実行時間に差がありません。

ただし、OSによってヒープの競合が発生している可能性があります。メモリを割り当てる必要があるたびに、他のスレッドがヒープから割り当て/解放していないことを保証するために、(ある種の、おそらくはspin_lockの) 'mutex'を制御する必要があります。これはあなたが経験している遅延を引き起こすでしょう。

+1

コードはそれなりに機能し、約100 usecsと300+ usecsが得られます。私もあなたのコードを試しましたが、私はまだ同じ問題があります。あなたのお時間をありがとう、私はそれを感謝します。私はちょうどヒープ上のOSとmutexに関するあなたの編集を見た。両方のケースでこれが問題になるはずはありませんか?なぜ彼らはその1つではっきりしないだろう – Pol

+0

ヒープの競合についての私の更新を読んだことがありますか?私たちのアーキテクチャはヒープを別々に扱っていると思います。 –

+0

この場合、ヒープ競合はありません。 @Polループの前にいくつかのデータで 'buff'を埋めてください。物理的なメモリに 'buff 'が割り当てられているために、おそらく追加の遅延が発生します。 –

0

'コピー'機能が呼び出されたときに、プロセスのスレッド数に差異があるようです。メインスレッドから呼び出されたときに、すでに終了した「何もない」スレッドが存在するので、そのプロセスのスレッドは1つだけです。しかし、 'mem'スレッドから呼び出されている間に、システム内には実質的に2つのスレッドがあります。これは、システムがロードされている場合や、プロセスのスレッド間に競合がある場合に違いを生む可能性があります。この時間差は、別のマシンや負荷の低いマシンで実行されている場合には、存在しない可能性があります。この理論は、無作為のスレッドで待機し、コピー関数が呼び出された後でのみキャンセルするようにコードを変更することによって検証できます。

+0

あなたは正しいです、コピーは結合の前になければなりません。私はこれを修正しましたが、私はまだ同じ結果を持っています。訂正していただきありがとうございます。 – Pol

関連する問題