4

ARMv7コアにイメージをコピーしたい。単純な実装は、行ごとにmemcpyを呼び出すことです。

for(i = 0; i < h; i++) {
  memcpy(d, s, w);
  s += sp;
  d += dp;
}

私は次のことを知っています

d, dp, s, sp, w

すべて32バイトで整列されているので、次の(まだかなりナイーブな)実装は次のようになりました。

for (int i = 0; i < h; i++) {
  uint8_t* dst = d;
  const uint8_t* src = s;
  int remaining = w;
  asm volatile (
    "1:                                               \n"
    "subs     %[rem], %[rem], #32                     \n"
    "vld1.u8  {d0, d1, d2, d3}, [%[src],:256]!        \n"
    "vst1.u8  {d0, d1, d2, d3}, [%[dst],:256]!        \n"
    "bgt      1b                                      \n"
    : [dst]"+r"(dst), [src]"+r"(src), [rem]"+r"(remaining)
    :
    : "d0", "d1", "d2", "d3", "cc", "memory"
  );
  d += dp;
  s += sp;
}

これは、多数の反復でmemcpyよりも約150%高速でした(異なるイメージで、キャッシュを利用していません)。まだプリロードを使用していないので、これは最適とは言えない気がしますが、使用するとパフォーマンスが大幅に低下するだけのようです。誰かがここで何か洞察を持っていますか?

4

1 に答える 1

5

ARMには、これに関する優れた技術ノートがあります。

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka13544.html

あなたのパフォーマンスはマイクロアーキテクチャによって間違いなく異なります。ARMのメモはA8にありますが、それはあなたにまともなアイデアを与えると思います。下部の要約は、単なるどのメソッドがレジスタの使用量を最小にするかなどの通常の数値など。

そして、はい、別のコメント提供者が言及しているように、プリフェッチを正しく行うことは非常に困難であり、キャッシュの大きさ、各行の大きさ、およびキャッシュに関するその他の詳細に応じて、さまざまなマイクロアーキテクチャで異なる動作をします設計。注意しないと、必要なラインをスラッシングしてしまう可能性があります。ポータブルコードでは避けることをお勧めします。

于 2013-02-12T16:46:55.910 に答える