質問ではC++について言及しましたが、C#(.NET 4.5)で3x3行列乗算C = A * Bを実装し、最適化を行った64ビットWindows7マシンでいくつかの基本的なタイミングテストを実行しました。10,000,000回の乗算に約
- ナイーブな実装で0.556秒
- 他の答えからのladermanコードで0.874秒。
興味深いことに、ladermanコードは素朴な方法よりも遅かった。私はプロファイラーで調査しませんでしたが、追加の割り当ては、いくつかの追加の乗算よりもコストがかかると思います。
現在のコンパイラは、これらの最適化を実行するのに十分賢いようです。これは良いことです。これが私があなたの興味のために使った素朴なコードです:
public static Matrix3D operator *(Matrix3D a, Matrix3D b)
{
double c11 = a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31;
double c12 = a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32;
double c13 = a.M11 * b.M13 + a.M12 * b.M23 + a.M13 * b.M33;
double c21 = a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31;
double c22 = a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32;
double c23 = a.M21 * b.M13 + a.M22 * b.M23 + a.M23 * b.M33;
double c31 = a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31;
double c32 = a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32;
double c33 = a.M31 * b.M13 + a.M32 * b.M23 + a.M33 * b.M33;
return new Matrix3D(
c11, c12, c13,
c21, c22, c23,
c31, c32, c33);
}
ここで、Matrix3Dは不変の構造体(読み取り専用のdoubleフィールド)です。
トリッキーなことは、コードを測定するのではなく、コンパイラがコードを使って何をしたかではなく、有効なベンチマークを考え出すことです(大量の余分なものを含むデバッガー、または結果が使用されなかったため、実際のコードなしで最適化されます)。私は通常、コンパイラがテスト対象のコードを削除できないように、結果を「タッチ」しようとします(たとえば、行列要素が89038.8989384と等しいかどうかを確認し、等しい場合はスローします)。しかし、結局、コンパイラがこの比較を邪魔にならないようにハックするかどうかさえわかりません:)