2016-05-04 21 views
1

Cで2つの行列の間にKhatri Raoプロダクトを実装する必要があります。数学的には、これはデータの主なアクセスであり、変更できません。しかし、プリロード(ARMv7でPLD命令)を使用して次のループの各データをプリフェッチすると、行の主なデータアクセスを使用する代わりにパフォーマンスの問題が解決されます。C言語でのARMv7でのプリフェッチ

「はい」の場合は正しくプリロードするにはどうすればよいですか?

以下の私のプリロード・コードを確認してください、

void khatrirao_pref(double *C, double *A, double *B, 
        int nmax, int mmax, int pmax) 
{ 
    int i,k,l; 
    for (i=0;i<nmax;i++) 
    { 
    for (k=0;k<mmax;k++) 
     { 
     asm("PLD [%0]\n\t" :: "r" (A+i+((nmax+1)*k)));  
     for (l=0;l<pmax;l++) 
    { 
      asm("PLD [%0]\n\t" :: "r" (B+i+((nmax+1)*l))); 
      C[i+(nmax*((k*pmax)+l))]=A[i+(nmax*k)]*B[i+(nmax*l)]; 
    }}} 
} 
+0

いつもカラムメジャー順を使うつもりなら、あなたは 'A [row] [col]'を持っていた配列インデックスの意味を逆にしてカラムを行と行として扱うことができるかどうかを考えてみましょう。 '' [col] [row] '。これにより、メモリ・シーケンスでデータにアクセスすることによるキャッシュの利点が得られます。それは軽く行うことではなく、非常に注意深く測定してテストすることです。 –

+0

@JonathanLefflerこんにちはJonathan、返事ありがとうございます。しかし、私はそうすることはできません。私は厳密に主要なアクセスをcollumnにとどまらなければなりません。私は内側の方程式や3つのループの順序や配列の次元を変更することはできません。私はプリフェッチを使って、同じ列のAとBの次のループデータを得ることができます。私はこれが奇妙なことを知っています。私は尋ねています。どう思いますか ? – karnajitsen

+0

あなたのメモリアクセスパターンで "穀物と反対"に行くことは間違いなく性能を損なうでしょう。より良い計画は、このコードに到達する前に、配列全体をキャッシュにプリフェッチすることです。書かれているように、先読みは役に立たないでしょう。あなたはCPUにヒントを与え、実際に読書をする時間を与える必要があります。 – BitBank

答えて

4

プリロード命令は、同様に、独自のコストを持っています。通常は、実際に読んでいるときより先にあらかじめ読み込み、慎重にプロファイルしたいと思っています。

これは、gccまたはclangの場合、明示的なインラインasmではなく、__builtin_prefetchを使用したほうが、サポート対象のPLD(ARMv5TE以降)ではコンパイルされますが、それ以外は無害です。私はいくつかの例で、実世界の使用状況を示す、このブログの記事を見つけました:

http://www.naftaliharris.com/blog/2x-speedup-with-one-line-of-code/

これはまた、PLDの使用方法を理解する上で非常に役立つリンクです:このページショーという

http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka13544.html

注意PLDを使用することは時には不利になることがあります。私の推測では、少なくともあなたの内側のループでそれを発行したくないということです。間違いなく別のケースを試してみるべきです。

マトリクスの最も一般的なサイズに応じて、特定のnmax/mmax値の特別な場合にも有益です。

+0

しかし、私はARMv7プロセッサを使用しています。__builtin_prefetchはそこで動作しますか?私はPLDがそうするよう指示されるべきだと思う。 – karnajitsen

+0

はい、gcc/clangにその命令を出すように指示する方法です。 –