1000 万の大きなベクトルに、それらすべてに同じ巨大な行列を掛けます。考えられるすべての意思決定を事前にまとめることができれば、最も速いでしょう。言い換えれば、同じように何百万回も繰り返される多くのインデックス計算とループ テストがあります。これは、プリコンパイルの完璧なケースのように思えます。
200x200 行列データ値を入力として受け取り、入力ベクトルを入力して結果ベクトルを出力できる関数を定義するプログラム テキストを出力する小さなプログラムを作成します。次のようになります。
void multTheMatrixByTheVector(double a[200], double b[200]){
b[0] = 0
+ a[0] * <a constant, the value of mat[0][0]>
+ a[1] * <a constant, the value of mat[1][0]>
...
+ a[199] * <a constant, the value of mat[199][0]>
;
b[1] = 0
+ a[0] * <a constant, the value of mat[0][1]>
+ a[1] * <a constant, the value of mat[1][1]>
...
+ a[199] * <a constant, the value of mat[199][1]>
;
...
b[199] = etc. etc.
}
おわかりのように、その関数は約 40000 行の長さになりますが、まともなコンパイラはそれを処理できるはずです。もちろん、行列要素のいずれかが 0 の場合、つまりスパース性がある場合は、それらの行を省略できます (またはコンパイラ オプティマイザに任せます)。CUDA またはベクトル化された命令でこれを行うには、それに応じて変更する必要がありますが、それは実行できるはずです。
その関数をメイン プログラムに含めると、マシンが実行できる速度とほぼ同じ速度で実行できるはずです。インデックス計算、ループ テスト、または空の行列セルによる乗算を行うサイクルを無駄にしません。
次に、乗算と加算ごとに 10ns かかる場合、封筒の裏には、ベクトルごとに 400 usec、または全体で 4000 秒かかるはずであると書かれています - 1 時間強です。