2017-09-08 7 views
0

私は、それぞれ64ビット長の8つのビットベクトルを含むデータ構造を持っています。しかし、これらの配列の個々のバイトは、順番に並べるのではなく、データ構造全体にインターリーブされ、与えられたビットベクトルの各連続するバイトは、前のバイトの後の8バイトです。現代のx86-64 CPUでは、インターリーブされたこれらのアレイと64ビットワードの間でデータを移動するための効率的な方法(パラレルロードやストアなど)はありますか?組み込みのasmを使用したCコードはうまくいきますが、gcc組み込み関数を使用するソリューションがあれば、それはさらに優れています。インターリーブアレイを読み書きする方法は?

+3

これを達成するにはいくつかの興味深いテクニックがあるかもしれませんが、いくつかのサンプルデータと、達成したい結果の最適化されていないバージョンであっても、それが立っているので、細部を知らなくても非常に広い質問です。 –

+1

これを行う巧妙な方法があるかもしれませんが(VPSHUFBは心に浮かんでいます)、このデータをたくさん読み込んでいない限り、それらを書き、テストする時間と努力があなたを大幅に節約することはほとんどありません。 SBSのソリューションは、AVX2やAVX512BWを使ってasmで書かれたものほどセクシーではないかもしれませんが、はるかに移植性と保守性に優れています。これがあなたのコードでパフォーマンスのボトルネックにならない限り、私はシンプルでシンプルに投票します。 –

答えて

0

私はそのようなインターリーブされたデータで動作するx64 CPU命令を認識していません。しかし、これらのCPUは、シフトおよびI/O、私は8インライン化シフト/コピー操作で、次のアプローチを使用して、オプティマイザに残りの仕事を残したいインデックス化にかなり速いですので、:

void Write (unsigned char*  bytes, 
      unsigned long long value, 
      int    offset) 
    { 
    bytes [offset  ] = (unsigned char) (value  ); 
    bytes [offset + 8] = (unsigned char) (value >> 8); 
    bytes [offset + 16] = (unsigned char) (value >> 16); 
    bytes [offset + 24] = (unsigned char) (value >> 24); 
    bytes [offset + 32] = (unsigned char) (value >> 32); 
    bytes [offset + 40] = (unsigned char) (value >> 40); 
    bytes [offset + 48] = (unsigned char) (value >> 48); 
    bytes [offset + 56] = (unsigned char) (value >> 56); 
    return; 
    } 

void Read (unsigned char*  bytes, 
      unsigned long long* value, 
      int     offset) 
    { 
    *value = ((unsigned long long) bytes [offset  ]  ) | 
      ((unsigned long long) bytes [offset + 8] << 8) | 
      ((unsigned long long) bytes [offset + 16] << 16) | 
      ((unsigned long long) bytes [offset + 24] << 24) | 
      ((unsigned long long) bytes [offset + 32] << 32) | 
      ((unsigned long long) bytes [offset + 40] << 40) | 
      ((unsigned long long) bytes [offset + 48] << 48) | 
      ((unsigned long long) bytes [offset + 56] << 56); 
    return; 
    } 

このコードを格納リトルエンディアン順の64ビット値ビッグエンディアンの場合、逆の順序でバイトを読み書きします。

関連する問題