C プロジェクトの行列処理関数を設計しています。行列を値または参照で渡すことを検討しています。値と参照で行列を渡すベンチマークを作成しましたが、どちらも gcc の最適化フラグ -O0 と -O2 で同じように動作するようです。私のベンチマークが間違った結果を示している可能性があることを考えると、C のみを使用して関数呼び出しの内外で行列を渡す最も効率的な方法を知りたい.
#include <stdio.h>
#include <time.h>
// Compiled on OSX 10.6.8 using: cc -o matrix matrix.c -std=c99 -O2
typedef struct {
float m0;
float m1;
float m2;
float m3;
float m4;
float m5;
float m6;
float m7;
float m8;
float m9;
float m10;
float m11;
float m12;
float m13;
float m14;
float m15;
} Matrix;
// ================================================
// Pass By Value
// ------------------------------------------------
Matrix PassByValue (Matrix a, Matrix b) {
Matrix matrix;
matrix.m0 = a.m0 * b.m0 + a.m4 * b.m1 + a.m8 * b.m2 + a.m12 * b.m3;
matrix.m1 = a.m1 * b.m0 + a.m5 * b.m1 + a.m9 * b.m2 + a.m13 * b.m3;
matrix.m2 = a.m2 * b.m0 + a.m6 * b.m1 + a.m10 * b.m2 + a.m14 * b.m3;
matrix.m3 = a.m3 * b.m0 + a.m7 * b.m1 + a.m11 * b.m2 + a.m15 * b.m3;
matrix.m4 = a.m0 * b.m4 + a.m4 * b.m5 + a.m8 * b.m6 + a.m12 * b.m7;
matrix.m5 = a.m1 * b.m4 + a.m5 * b.m5 + a.m9 * b.m6 + a.m13 * b.m7;
matrix.m6 = a.m2 * b.m4 + a.m6 * b.m5 + a.m10 * b.m6 + a.m14 * b.m7;
matrix.m7 = a.m3 * b.m4 + a.m7 * b.m5 + a.m11 * b.m6 + a.m15 * b.m7;
matrix.m8 = a.m0 * b.m8 + a.m4 * b.m9 + a.m8 * b.m10 + a.m12 * b.m11;
matrix.m9 = a.m1 * b.m8 + a.m5 * b.m9 + a.m9 * b.m10 + a.m13 * b.m11;
matrix.m10 = a.m2 * b.m8 + a.m6 * b.m9 + a.m10 * b.m10 + a.m14 * b.m11;
matrix.m11 = a.m3 * b.m8 + a.m7 * b.m9 + a.m11 * b.m10 + a.m15 * b.m11;
matrix.m12 = a.m0 * b.m12 + a.m4 * b.m13 + a.m8 * b.m14 + a.m12 * b.m15;
matrix.m13 = a.m1 * b.m12 + a.m5 * b.m13 + a.m9 * b.m14 + a.m13 * b.m15;
matrix.m14 = a.m2 * b.m12 + a.m6 * b.m13 + a.m10 * b.m14 + a.m14 * b.m15;
matrix.m15 = a.m3 * b.m12 + a.m7 * b.m13 + a.m11 * b.m14 + a.m15 * b.m15;
return matrix;
}
// ================================================
// Pass By Reference
// ------------------------------------------------
void PassByReference (Matrix* matrix, Matrix* a, Matrix* b) {
if (!matrix) return;
if (!a) return;
if (!b) return;
matrix->m0 = a->m0 * b->m0 + a->m4 * b->m1 + a->m8 * b->m2 + a->m12 * b->m3;
matrix->m1 = a->m1 * b->m0 + a->m5 * b->m1 + a->m9 * b->m2 + a->m13 * b->m3;
matrix->m2 = a->m2 * b->m0 + a->m6 * b->m1 + a->m10 * b->m2 + a->m14 * b->m3;
matrix->m3 = a->m3 * b->m0 + a->m7 * b->m1 + a->m11 * b->m2 + a->m15 * b->m3;
matrix->m4 = a->m0 * b->m4 + a->m4 * b->m5 + a->m8 * b->m6 + a->m12 * b->m7;
matrix->m5 = a->m1 * b->m4 + a->m5 * b->m5 + a->m9 * b->m6 + a->m13 * b->m7;
matrix->m6 = a->m2 * b->m4 + a->m6 * b->m5 + a->m10 * b->m6 + a->m14 * b->m7;
matrix->m7 = a->m3 * b->m4 + a->m7 * b->m5 + a->m11 * b->m6 + a->m15 * b->m7;
matrix->m8 = a->m0 * b->m8 + a->m4 * b->m9 + a->m8 * b->m10 + a->m12 * b->m11;
matrix->m9 = a->m1 * b->m8 + a->m5 * b->m9 + a->m9 * b->m10 + a->m13 * b->m11;
matrix->m10 = a->m2 * b->m8 + a->m6 * b->m9 + a->m10 * b->m10 + a->m14 * b->m11;
matrix->m11 = a->m3 * b->m8 + a->m7 * b->m9 + a->m11 * b->m10 + a->m15 * b->m11;
matrix->m12 = a->m0 * b->m12 + a->m4 * b->m13 + a->m8 * b->m14 + a->m12 * b->m15;
matrix->m13 = a->m1 * b->m12 + a->m5 * b->m13 + a->m9 * b->m14 + a->m13 * b->m15;
matrix->m14 = a->m2 * b->m12 + a->m6 * b->m13 + a->m10 * b->m14 + a->m14 * b->m15;
matrix->m15 = a->m3 * b->m12 + a->m7 * b->m13 + a->m11 * b->m14 + a->m15 * b->m15;
}
// ================================================
// Benchmark
// ------------------------------------------------
#define LOOPS 100000
int main () {
Matrix result;
Matrix a;
Matrix b;
clock_t begin;
clock_t end;
int index;
// ------------------------------------------
// Pass By Reference
// ------------------------------------------
begin = clock();
for (index = 0; index < LOOPS; index++) {
PassByReference(&result,&a,&b);
a.m0 += index;
b.m0 += index;
}
end = clock();
printf("Pass By Ref: %f\n",(double)(end - begin) / CLOCKS_PER_SEC);
// ------------------------------------------
// Pass By Value
// ------------------------------------------
begin = clock();
for (index = 0; index < LOOPS; index++) {
result = PassByValue(a,b);
a.m0 += index;
b.m0 += index;
}
end = clock();
printf("Pass By Val: %f\n",(double)(end - begin) / CLOCKS_PER_SEC);
// The following line along with the above
// additions in the loops hopefully prevent
// the matrices from being optimized into
// nothing.
printf("%0.1f\n",result.m0);
return 0;
}
結果:
Pass By Ref: 0.489226
Pass By Val: 0.488882