2016-04-01 9 views
0

私はパフォーマンス上の理由から型打ちを行う関数を持っています。基本的に、私は32 uint32sの配列として格納された32×32ビットの配列を持っている:-fno-strict-aliasingを関数属性として指定します。

struct Tile { 

    uint32_t d[32]; 

}; 

私はその後、内部28「・バイ・28の(1の人口の数) 『を計算したいです』 32×32タイルの素朴な方法では、マシンのpopcnt命令を各行に1つずつ、28回コールします。しかしPOPCNTは、64ビットの引数を取ることができるので、これは14回のPOPCNT呼び出しに減らすことができます:私は属性含まれていない場合は

int countPopulation(Tile* sqt) __attribute__((optimize("-fno-strict-aliasing"))) { 

    int pop = 0; 

    for (int i = 2; i < 30; i += 2) { 
     const uint64_t v = *reinterpret_cast<const uint64_t*>(sqt->d + i); 
     pop += __builtin_popcountll(v & 0x3ffffffc3ffffffcull); 
    } 

    return pop; 

} 

:その後、

__attribute__((optimize("-fno-strict-aliasing"))) 

グラムを++私は私をすれば、一方

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing] 
     const uint64_t v = *reinterpret_cast<const uint64_t*>(sqt->d + i); 

:常に私のタイプ-punningについて、明白な理由のために、文句を言うでしょう特定のバージョンのg ++​​が不平を言っているのに対し、属性をncludeしています。私はこれを試したているマシンの中で、私が取得:

  • グラム++(Ubuntuの〜14.04.1 4.8.4-2ubuntu1)4.8.4 がg ++
  • を不平を言う - 4.6.real(Ubuntuの/リナロ4.6.3-1ubuntu5)4.6.3
  • グラム++(Debianの5.3.1-5)5.3.1 20160101 をgのUbuntuの味と間違って何

を文句はありません文句はありません++ 4.8.4?

+0

*私はパフォーマンス上の理由からタイプ・パンニングしています* - ここでは誤りがあります。 – SergeyA

答えて

0

入力しないでください。これには理由はありません。代わりにint64_t引数との間でコピーする場合は、memcpy()を正しく使用してください。オプティマイザは残りの作業を行います。

+0

ありがとうございます。私はstd :: memcpyとreinterpret_castの両方でアセンブリコードを生成し、それらは同じものです。 –

+0

@ AdamP.Goucher、もちろんそうです。あなたが見ているように、オプティマイザは開発者のために開発者のために書かれています。私たちの命を耐え難くしたいと思っている外国人モンスターではなく、D – SergeyA

+0

1989年にはコンパイラがmemcpyを使用してエイリアシング制限を避けるべきだという人はいませんでした部屋から出て行って、全然避けていなければ。この標準の目的は、コンパイラが、エイリアスへのポインタを期待する理由がない場合に、エイリアスについての悲観的な前提を作ることを避けることでした。コードがオブジェクトのアドレスを受け取り、問題のオブジェクトへの次のアクセスの前にストレージ*にアクセスする*を入力します。いくつかのコンパイラライターは鈍いです... – supercat

関連する問題