SSEを使用した単純なZeroMemory実装が必要です(SSE2を推奨)誰かがそれを手伝ってくれますか?私はSOとネットを介して検索していましたが、それに対する直接の答えは見つかりませんでした。
3 に答える
十分ですかZeroMemory()
?memset()
免責事項: 以下の一部は SSE3 である可能性があります。
- アドレスが 16 の倍数になるまでループして、アラインされていない先行バイトを埋める
push
xmm reg を保存するにはpxor
xmm reg をゼロにする- 残りの長さ >= 16 の間、
movdqa
またはmovntdq
書き込みを行う
pop
xmm reg を復元します。- アラインされていない末尾のバイトを埋めます。
movntdq
データをキャッシュに取り込まないようにプロセッサに指示するため、高速に見えるかもしれませんが、データが使用される場合、後でパフォーマンスが低下する可能性があります。メモリを解放する前にスクラブしている場合 ( の場合のように)、より適切な場合がありますSecureZeroMemory()
。
CPU がどのように機能し、ボトルネックがどこにあるかを正確に理解する必要があるよりも、コードを高速化したいと考えています。
ここでは、どのように作成する必要があるかを示すために、速度を最適化したルーチンを示します。
私のPCでは、あなたのPCよりも約5倍高速です(1MBytesのメモリブロックをクリアします)。テストして、何かが明確でないかどうか尋ねてください:
//edx = memory pointer must be 16 bytes aligned
//ecx = memory count must be multiple of 16
xorps xmm0, xmm0 //Clear xmm0
mov eax, ecx //Save ecx to eax
and ecx, 0FFFFFF80h //Clear only 128 byte pages
jz @ClearRest //Less than 128 bytes to clear
@Aligned128BMove:
movdqa [edx], xmm0 //Clear first 16 bytes of 128 bytes
movdqa [edx + 10h], xmm0 //Clear second 16 bytes of 128 bytes
movdqa [edx + 20h], xmm0 //...
movdqa [edx + 30h], xmm0
movdqa [edx + 40h], xmm0
movdqa [edx + 50h], xmm0
movdqa [edx + 60h], xmm0
movdqa [edx + 70h], xmm0
add edx, 128 //inc mem pointer
sub ecx, 128 //dec counter
jnz @Aligned128BMove
@ClearRest:
and eax, 07Fh //Clear the rest
jz @Exit
@LoopRest:
movdqa [edx], xmm0
add edx, 16
sub eax, 16
jnz @LoopRest
@Exit:
CPU のほぼすべてのトランジスタは、何らかの方法でメモリ アクセスを可能な限り高速化するために使用されます。CPU はすでにすべてのメモリ アクセスで驚くべき仕事をしており、命令は可能なメモリ アクセスよりも大幅に速い速度で実行されます。
したがって、 memset を打ち負かすことは、ほとんどの場合、ほとんど無駄な作業です。これは、メモリの速度によって既に制限されているためです (他の人が述べたように)。