質問

私は、行列演算の多くをやっているし、C99のrestrictポインタ修飾子を利用したいと思います。

私はそうのような簡単な添字を可能にするために、ポインタへのポインタとして設定私の行列をしたいのですが

int **A = malloc (ncols * sizeof(int *));
A[0] = malloc (nrows * ncols * sizof(int));
for (int i=1; i < ncols; i++) {
    A[i] = A[0] + i*nrows;
}

さて、行列乗算機能のための

void mmultiply ( int nrows, int ncols, int **Out, int **A, int **B);
制限付きとして

私は、引数の両方のポインタを修飾する必要がありますか?それは有効な構文ですが、私はint *restrict *restrictはどんな異なったint **restrictより振る舞うかどうかを判断するに苦労しています。

次に、適切に制限されたポインタで、A[0][col*nrows + row]未定義を通じて要素にアクセスしていますか? (すなわち、コンパイラは私がのことを前提としていますのみA[col][row]の値は、このようなrowそのためrow < nrowて行列にアクセスしますか)?それとも私は単純に一貫性を維持しなければならない?

役に立ちましたか?

解決

あなたは両方のrestrict修飾子を使用する場合は、

最初の質問については、「はい」、それはポインタもエイリアスされないことを、具体的には、何か別のことを意味します。それはどんな違いをかどうかについて:理論的には、はい、実際には、オプティマイザによって異なります。

2番目の質問については、「はい」、それは行ポインタを介してアクセスするもののみ行ポインタを介してアクセスされることを前提としています。

あなたもそこにconstを投げることができます。

これは-O2、-O3、または-Osでgccのであれば、

最後に、コンパイラがすでにタイプに基づいてエイリアス解析を行っています。私は他のコンパイラでもこれを行うと確信しています。これは、おそらく互いに保存できる唯一の配列を残し、int型対ポインタを規制が既に理解されていることを意味します。

要するに、オプティマイザはポインタはint型とに格納されていないことを前提とし、それがループの中に書き込まれ、それは任意のポインタをやっていません知っています。

だから、あなたはおそらく唯一の制限と同じコードを取得します。

他のヒント

(第2)の外側には、制限することをポインタの配列のいずれも(A、B、およびアウト)別名コンパイラに指示します。内側の(最初の)制限intの配列のいずれもエイリアス(ポインタの配列の要素によって指さない)。

コンパイラに指示 あなたがA [0] [COLは、* +行をNROWS]とA [COL] [行]の両方にアクセスする場合は、

あなたは物事を壊すかもしれないので、内側には、制限に違反しています。

int **restrictだけでアウト、AおよびBによってアドレスされたメモリ(つまりA以外とBは、あなたの関数は、それらのいずれかを変更しないと仮定すると、重複することができます)重複していないと主張しています。これは、ポインタの配列を意味しています。これは、メモリの内容については何も主張しないn1124でアウト、A、Bの脚注117で指されることは言います:

  

識別子pは(int型を持つ場合   **制限する)、次いで、ポインタ式PとP + 1に基づいています   指定された制限されたポインタオブジェクト   Pによるが、ポインタ式* P   pは、[1]ない。

const類推し、私はrestrictで予選は二回のメモリをオーバーラップする配列ポイントの値のいずれもということである、あなたが望むものを主張することを疑います。しかし、標準を読んで、私はそれが実際にないこと自分自身に証明することはできません。私は確かint *restrict *restrict Aため、次に[0]、A [1]であることを意味し、「DはT型に制限する修飾ポインタとして被検体Pを指定する手段を提供する通常の識別子の宣言とする」ことを数えますintへの制限修飾ポインタとして指定されたオブジェクト。しかし、それはかなり重い法律用語です。

私はあなたのコンパイラは、実際にその知識、あなたの心に何かをするかどうかはわかりません。明らかにそれができた、それが実装されていますかどうかの問題だ。

私は本当にあなたがちょうどrows * cols * sizeof(int)A[cols*row + col]、およびインデックスを割り当てる従来のC 2-D列、上で得てきたのか分からないようにします。そして、あなたは明らかにのみ制限の一つの使用を必要とし、restrictで何もしない任意のコンパイラは、再注文がアウトに書き込み全体でAとBから読み込むことができるようになります。 restrictがなければ、もちろん、それは、あなたが何をやっているやっによって、あなたは、コンパイラの慈悲に身を投げていることはできません。それは二重制限する、唯一の制限場合に対応できない場合は、お使いのダブル間接はあなたに最適の費用います。

最初の推測では、乗算はとにかく追加のポインタの間接よりも高速である可能性が高いです。あなたは明らかパフォーマンスを気にしたりはまったく制限する使用されないので、私は少しよりよい構文のために、この変更を行う前に(すべてのコンパイラには、あなたが気に)かなり慎重にパフォーマンスをテストしたいとどのように多くの覚えていません列あなたがそれにアクセスするたびに、あなたの配列であります。

未定義[COLが* +行をNROWS] [0]を介して要素にアクセスしている

はい、これはまた、[COL]を介してアクセスされたメモリのための[0]エイリアスを作るための要素は、アクセスのいずれかによって修飾されている場合。 [0]とA [COL]であれば、AとBのみが制限修飾ポインターだったが、ない場合には、罰金になると思います。

私は実際にそのエイリアスは結構です、あなたがこの機能には変更しないことを前提としています。あなたがアウトと同じことをした場合は、しかし、動作は未定義になります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top