2012-09-25 12 views
10

編集:STは、初心者のために2つ以上のリンクを投稿することを許可していません。不足している参照を申し訳ありません。キャッシュラインアラインメントを使用したCのグローバル共有状態の変更のロックフリーチェック

グローバルな状態で変更が検出されたことがパフォーマンスに関連するCアプリケーションで、ロックオーバーヘッドを減らそうとしています。最近、話題についてかなり多くのことを読んでいましたが(例:H. Sutterなど)、私の実装については自信を持っていません。私はキャッシュライン整列グローバル変数のチェックのためにCASのような操作とDCLの組み合わせを使用して、誤った共有を回避し、複数のスレッド間で共有されたデータからスレッドローカルデータを更新したいと考えています。自信の私の欠如は、私は簡単なaligning-として、Cに変換する可能性のある文学と例を見つけることができないように見えるため、

  1. 私はType-Attributes
  2. にGNUのドキュメントを解釈するために失敗に主ですキャッシュ・ライン・アンド・知って・キャッシュ・ライン・サイズをSTまたは1
  3. はCとの私の経験がある(は多少、私は私の実装に自信がないんだけど、私の質問に答えるようだが)限定
件の

私の質問:

  1. タイプ属性のドキュメントの状態:

    この属性は、指定された 型の変数(バイト)最小アラインメントを指定します。例えば、宣言:

    (宣言のタイプ属性のドキュメントを参照してください)

    力コンパイラは、(限り、それはできる限り)、そのタイプの各変数は、struct S 又はmore_aligned_intが割り当てられるとであることを保証するために少なくとも8-byte境界に位置合わせされる。 SPARCでは、タイプstruct Sのすべての変数を8-byteの境界に揃えておくと、struct Sタイプの変数 を別のフロッピーにコピーするときに コンパイラがlddおよびstd(ダブルワードのロードおよびストア)命令を使用して実行時の効率が向上します。それはstruct Sまたはmore_aligned_intの始まりは常に8-byte境界に整列されることを

    を意味するのでしょうか?データが正確に64バイトを使用するように埋められることを意味するのではないでしょうか?

  2. と仮定します。struct cache_line_alignedのすべてのインスタンスは、(下記のコード例1参照)64-byte境界に整列し、正確に一つのキャッシュラインを利用することは事実であるタイプ宣言がないためtypedefを使用

  3. (キャッシュラインを仮定し、長さが64 bytesです) __attribute__ ((aligned (64)))のセマンティクスを変える構造体が__attribute__ ...

  4. と宣言されている場合、構造体のインスタンスを作成する際に、私は aligned_mallocを使用する必要はありません

  5. (以下のコード例2を参照してください)

// Example 1 
struct cache_line_aligned { 
 int version; 
 char padding[60]; 
} __attribute__ ((aligned (64))); 

// Example 2 
typedef struct { 
 int version; 
    // place '__attribute__ ((aligned (64)))' after 'int version' 
    // or at the end of the declaration 
 char padding[60]; 
} cache_line_aligned2 __attribute__ ((aligned (64))); 

そして最後にグローバルな状態が他のスレッドによって変更されたかどう効率的にチェックするためにキャッシュライン整列アプローチを使用する関数のスケッチ:

void lazy_update_if_changed(int &t_version, char *t_data) { 
    // Assuming 'g_cache_line_aligned' is an instance of 
    // 'struct cache_line_aligned' or 'struct cache_line_aligned2' 
    // and variables prefixed with 't_' being thread local 
    if(g_cache_line_aligned.version == t_version) { 
    // do nothing and return 
    } else { 
    // enter critical section (acquire lock e.g. with pthread_mutex_lock) 
    t_version = g_cache_line_aligned.version 
    // read other data that requires locking where changes are notified 
    // by modifying 'g_cache_line_aligned.version', e.g. t_data 
    // leave critical section 
    } 
} 

長い記事のために申し訳ありません。

ありがとうございました!

答えて

7

たとえば、8バイト境界にアライメントされた整列型を定義する場合、コンパイラーは、その型を複数の整列(ここでは8バイトの倍数)にパディングする必要があります。

その理由は簡単です。その整列した型の配列を定義したいとします。当然、それのすべての要素も整列されるべきです。そのためにパディングがあるのです。

#include <stdio.h> 

struct cache_line_aligned { 
    int version; 
// char padding[60]; 
} __attribute__ ((aligned (64))); 

int main(void) 
{ 
    struct cache_line_aligned s; 
    struct cache_line_aligned a[2]; 
    printf("sizeof(struct cache_line_aligned) = %d\n", (int)sizeof(struct cache_line_aligned)); 
    printf("sizeof(s) = %d\n", (int)sizeof(s)); 
    printf("sizeof(a[0]) = %d\n", (int)sizeof(a[0])); 
    printf("sizeof(a) = %d\n", (int)sizeof(a)); 
    return 0; 
} 

出力(ideone):

sizeof(struct cache_line_aligned) = 64 
sizeof(s) = 64 
sizeof(a[0]) = 64 
sizeof(a) = 128 

あなたが(ないmalloc()などを経由してIOW、)struct cache_line_aligned非動的のインスタンスを作成する場合は、同じよう

はここで少しデモです上記のコードでは、それは整列されます。 (1999から)

C標準はmalloc()calloc()realloc()に対する状態:で__attribute__ ((aligned (64)))のようなものがないためany type of objectは、上記構造体のような人工的に整列/パディングタイプを含まない

The pointer returned if the allocation succeeds is suitably aligned so that 
it may be assigned to a pointer to any type of object and then used to 
access such an object or an array of such objects in the space allocated 
(until the space is explicitly deallocated). 

Cの標準。これはGNUの拡張です。動的に割り当てられたオブジェクトを任意の位置に配置するには、適切なメモリ割り当て関数を使用するか、手動で配置を行う必要があります(メモリをさらに割り当て、ポインターの値を "整列"する)。

+0

乾杯!これは物事を非常によく分かりました。私はsizeofを使ってアラインメントをチェックすることを考えていませんでした!私はこれを覚えています。動的に割り当てられた構造体はどうでしょうか? 'aligned_malloc'は仕事をしますか? – instilled

+0

それはおそらくあります。その文書を読んで確認してください。 –

+0

そうするでしょう。華麗な答えにもう一度感謝します。 – instilled

関連する問題