2009-05-04 10 views
10

次のコードは、nとvの両方に対してランダムな値を生成します.nが適切に保護されていないとランダムであることは驚くことではありません。しかし、vは最終的に0になるはずです。私のコードに何か間違いはありますか?それとも誰も私のためにこれを説明することができますか?ありがとう。atomic.hからの操作は非アトミックなようです

私はx86アーキテクチャの4コアサーバーで作業しています。 unameは次のとおりです。

Linuxの2.6.9-22.ELsmp#1 SMP月9月19日18時00分54秒EDT 2005 x86_64のx86_64でのx86_64版は、GNU/Linuxの

#include <stdio.h> 
#include <pthread.h> 
#include <asm-x86_64/atomic.h> 

int n = 0; 
atomic_t v; 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

#define LOOP 10000 

void* foo(void *p) 
{ 
    int i = 0; 
    for(i = 0; i < LOOP; i++) { 
//  pthread_mutex_lock(&mutex); 
     ++n; 
     --n; 
     atomic_inc(&v); 
     atomic_dec(&v); 
//  pthread_mutex_unlock(&mutex); 
    } 

    return NULL; 
} 

#define COUNT 50 

int main(int argc, char **argv) 
{ 
    int i; 
    pthread_t pids[COUNT]; 
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    atomic_set(&v, 0); 

    for(i = 0; i < COUNT; i++) { 
     pthread_create(&pids[i], &attr, foo, NULL); 
    } 

    for(i = 0; i < COUNT; i++) { 
     pthread_join(pids[i], NULL); 
    } 

    printf("%d\n", n); 
    printf("%d\n", v); 
    return 0; 
} 
+5

私は答えはありませんが、私は言いたいことがあります:完全に動作するソースコードではっきりとした、明確な質問に感謝します。誰もがそうしたいと思う! – RichieHindle

答えて

3

コードのアセンブラ出力を見ることができますか(gcc -E、私は思う)。 unameがSMP対応であることを示しているとはいえ、必ずしもCONFIG_SMPでコンパイルされているとは限りません。

これがなければ、アセンブラコードの出力にはlockというプリフィックスがなく、コアが相互に干渉していることがわかります。

しかし、もっと多くのプラットフォームで移植可能なので、私はpthread関数を使用しています。

+4

ありがとうございます。 gcc -E出力にロックプレフィックスが見つかりませんでした。 を含める前に#define CONFIG_SMPを追加するだけで動作します。 このコードは、異なるスレッドセーフインクリメントアプローチの効率をテストするために使用されます。それは生産のためではありません。 :-) – Hank

4

This old post

  • それは明らかではないことを意味しユーザー空間プログラムにこのカーネルヘッダーを含めることになっていることを確認してください。
  • ユーザー空間プログラムにアトミック性を提供できないことが知られています。

これはおそらく、あなたが見ている問題の理由ですか?

+0

ありがとうございます。私はなぜLinuxカーネルがこれらの便利なプリミティブをユーザランドプログラムに公開しないのか不思議です。 pthread_mutexのアプローチよりも軽量で効率的です。 – Hank

+0

@よくも、カーネルは実際にはそうです。それを混乱させるglibc。 –

+0

@ハンク:まあ、うまくいかないから。アトミック操作では、プラットフォームによっては特権操作が必要です。カーネルやユーザーランドとはまったく異なる処理が必要です。 –

6

代わりにgcc組み込み関数を使用する必要があります(。thisを参照)。これはうまく動作し、iccでも動作します。

int a; 
__sync_fetch_and_add(&a, 1); // atomic a++ 

ロックしないで変数を変更する場合、キャッシュの一貫性の問題に注意する必要があります。

0

Linuxカーネルatomic.hはユーザランドからは使用できませんでした。 x86では、いくつかのプラットフォームが動作する可能性がありますが、x86は同期に優しいアーキテクチャですが、一部のプラットフォームでは、特権操作(古いバージョン)やプリエンプションを無効にできること(古いバージョンのarmとsparc少なくとも)、これはユーザーランドの場合ではありません!

関連する問題