2012-02-26 8 views
1

プログラムは複数のスレッドを作成し、forループを使用して各スレッドが共有変数を10000ずつインクリメントし、繰り返しごとに1ずつインクリメントします。 mutexロックとスピンロック(ビジー待機)の両方のバージョンが必要です。私が学んだことによると、ミューテックスのバージョンはスピンロックより速く動作するはずです。ミューテックスとビジー待機の効率測定

void *incr(void *tid) 
{ 
    int i; 
    for(i = 0; i < 10000; i++) 
    { 
     pthread_mutex_lock(&the_mutex);  //Grab the lock 
     sharedVar++; //Increment the shared variable 
     pthread_mutex_unlock(&the_mutex); //Release the lock 
    } 
    pthread_exit(0); 
} 

そして、これは、スピンロックバージョンで実装したものです::

void *incr(void *tid) 
{ 
    int i; 
    for(i = 0; i < 10000; i++) 
    { 
     enter_region((int)tid); //Grab the lock 
     sharedVar++;  //Increment the shared variable 
     leave_region((int)tid); //Release the lock 
    } 
    pthread_exit(0); 
} 
void enter_region(int tid) 
{ 
    interested[tid] = true;  //Show this thread is interested 
    turn = tid;  //Set flag 
    while(turn == tid && other_interested(tid)); //Busy waiting 
} 
bool other_interested(int tid) //interested[] is initialized to all false 
{ 
    int i; 
    for(i = 0; i < tNumber; i++) 
     if(i != tid) 
      if(interested[i] == true) //There are other threads that are interested 
       return true; 
    return false; 
} 
void leave_region(int tid) 
{ 
    interested[tid] = false; //Depart from critical region 
} 
しかし、私が実装する。これは、ミューテックスのバージョンでは、各スレッドのinplementationです...私に

を反対の答えを与えました

スレッドの作成と実行のプロセスを何百回も繰り返して、実行時間を区別できるようにしました。 たとえば、tNumberが4で、プログラムを1000回反復した場合、mutexは私に2.22秒かかり、スピンロックは1.35秒かかります。 tNumberが増加するにつれてその差は大きくなります。なぜこうなった?私のコードは間違っていますか?

+6

あなたの「スピンロック」は何もロックしません。それはマルチコアCPU上で正しく動作することはありません。確かに、ボルケンコードはもっと速くなる可能性があります。並行性と共有変数の値が間違っているかどうかを確認するためには、ループを長くする必要があります。 –

+2

@ HansPassant修正。私は、スピンロックの正しい実装は、ほとんどの場合、ある種のテスト&セットまたはロードリンク/ストア条件付きの構造を使用し、ハードウェア固有の傾向があると付け加えます。 –

+0

このコードは、大学のテストのコードとほぼ同じです。少なくとも私たちのところで。 – UmNyobe

答えて

0

enter_regionleave_regionのコードは保護されていません。

これを証明するには、自分自身を上に向けるようにもっと複雑にすることができます。

長さ10000のbool(チェック)の配列を作成し、falseに設定します。出入りの間のコードを作成します。

if (check[sharedVar]) cout << "ERROR" << endl; 
else check[sharedVar++] = true; 
+0

あなたの言ったように自分のコードを修正しましたが、実行中にSegmentation Fault ...が返されました私はこれらの2行をsharedVal ++に戻しました。それは正常に動作します。 – goldfrapp04

+0

おっと - 配列のサイズはtNumber * 1000でなければなりません。ごめんなさい。どちらの方法でも、他の人が指摘しているように、スピンロックはロックされません。 –

+0

ありがとうございます。私は2行を "if(!check [sharedVar])check [sharedVar ++] = true;"と書き直しました。実行時間はまだmutexの実行時間よりも短くなっています。あなたのコードは単にループを長くする、あるいは何らかの保護を行う目的のためだけですか?私はまだそれを得ることができません... – goldfrapp04

0

速度の「違い」は、一連の動作です

interested[tid] = true;  //Show this thread is interested 
turn = tid;  //Set flag 
while(turn == tid && other_interested(tid)); 

を使用して、同期を実装しているということです。彼がそれをしている間、どのスレッドも先取りすることができ、次のスレッドは誤った状態を読み取る。

compare-and-swapまたはtest-and-setのいずれかを実装することによって、アトミックに行う必要があります。これらの命令は、通常、ハードウェアによって提供されます。

あなたは問題が アトミックが高価であるということである

while(compare_and_swap_atomic(myid,id_meaning_it_is_free) == false); 

として xchg, cmpxchg/cmpxchg8b, xadd
あなたのテストを書き換えることができていたx86上の例の場合

+0

これを追加するだけで、C11ではspinlockの完全なプリミティブデータ型である 'atomic_flag'があります。 –

関連する問題