5

snappy の内部には、reinterpret_cast されたポインターの逆参照を選択する条件付きでコンパイルされたセクションがあります。これは、そのような操作をサポートすることが知られているアーキテクチャ上で、アライメントされていない可能性のある 16、32、および 64 ビット整数の読み取りと書き込みの最適な実装として選択します ( x86)。他のアーキテクチャのフォールバックは、memcpy ベースの実装を使用することです。

私の理解では、 reinterpret_cast 実装は未定義の動作を示し、clang の未定義動作サニタイザーはそれにフラグを立てます。

私を困惑させているのは、memcpyベースの実装を使用しないのはなぜですか? サイズはコンパイル時にわかっているため、最も壊れたコンパイラを除くすべてのコンパイラが組み込み関数を使用してこれらの memcpy 呼び出しを実装することを期待しています。実際、最新のツールチェーンの両方の実装から同一のコード生成が期待されます。

ただし、snappy は、その内容を熟知している人々によって書かれたものであることも認識しています。したがって、未定義の動作であることを上回る reinterpret_cast メカニズムを使用する利点がまだあるかどうか疑問に思います。パフォーマンスをコンパイラの実装品質に依存させたくないですか? 私が考慮していない他の何か?

4

2 に答える 2

4

そもそもそのコードを書いたプログラマーを知らなければ、真に信頼できる回答を得られるとは思えません。

これが私の最善の推測です。作成者は可能なmemcpy最適化に依存したくありませんでした (多くのコンパイラで実装されていても、仕様では決して保証されていません)。反対に、 a を書くreinterpret_castと、ほぼすべてのコンパイラで、作成者が期待していたアライメントされていないアクセス命令が生成される可能性が非常に高くなります。

スマートで最新のコンパイラは を最適化しますがmemcpy、古いものは最適化しない場合があります。このライブラリでは一貫したパフォーマンスが非常に重要にreinterpret_castなる可能性があるため、より幅広いコンパイラセットでより一貫した結果を得るために、ある程度の正確性を犠牲にしているようです (潜在的に UB のように見えるため)。

于 2014-08-19T05:44:42.030 に答える