2

Linux カーネルのソース コードには、多くのメモリ バリア (smp_mb() など) があります。

しかし、redisのソースでは、私はそれを見ませんでした。redis の Makefile では、gcc の最適化オプションが -O2 になっているため、これらの命令の順序を変更する必要があります。正しい動作を保証するために mb() を使用しないのはなぜですか?

追加した:

例: Linux カーネルの kfifo では:

unsigned int __kfifo_put(struct kfifo *fifo,unsigned char *buffer, unsigned int len)   
{   
  unsigned int l;   
  len = min(len, fifo->size - fifo->in + fifo->out);
  smp_mb();
  l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));   
  memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
  ...
  smp_wmb();
  fifo->in += len;
  ...
}

Redis ソースでは、プロジェクト全体を調査しましたが、メモリ バリアを見つけることができません。たとえば、次のようになります。

zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj) {
  zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
  unsigned int rank[ZSKIPLIST_MAXLEVEL];
  int i, level;
  ...
  level = zslRandomLevel();
  if (level > zsl->level) {
    for (i = zsl->level; i < level; i++) {
      rank[i] = 0;
      update[i] = zsl->header;
/////need a mb() ???
      update[i]->level[i].span = zsl->length;
    }
    zsl->level = level;
  }
  ...
}

なぜredisにメモリバリアがないのは特別ですか?
おそらく mb() に対する私の理解は未熟だと思います。コメントありがとうございます...

追加した:

しかし、上記の 2 つのコードでは、Linux カーネルの kfifo が mb() を使用しています。スレッドのスタック空間に割り当てられた変数と、r/w 操作の間のユーザー mb() を変更するだけです。したがって、マルチスレッドに完全に関連するわけではありません...(redisはシングルスレッドですが)

4

2 に答える 2

6

Redisはシングルスレッドであるため、メモリバリアは必要ありません。

これらは、複数の実行パスがある場合にのみ関係します(たとえば、マルチスレッドアプリケーションの場合)。マルチスレッドのユーザースペースアプリケーションでも、ライブラリ(pthreadなど)には同期API(ミューテックス、セマフォ、条件変数など)にメモリバリアが含まれているため、通常は独自のメモリバリアは必要ありません。

于 2013-01-06T16:23:50.960 に答える
6

明示的なメモリ バリアを必要とするコードはごくわずかであることを理解しておくと役立つ場合があります。このようなコードの例としては、OS カーネル、スレッド ライブラリ、ロックフリー データ構造などがあります。

他のほとんどのコードは次のいずれかになります。

  1. スレッディングと直接やり取りしないため、メモリバリアが不要になります。
  2. OS が提供するスレッド ライブラリ (例: ) を使用し、そのようなライブラリによって提供されるメモリ順序の保証pthreadsに依存します。

この質問をするときに、Redis のコード ベースの特定の部分を念頭に置いていた場合は、関連するコードを示してください。

于 2013-01-06T09:32:45.627 に答える