C函数调用导致的巨大开销
我有一个简单的函数,它将两个矩阵相乘C函数调用导致的巨大开销,c,performance,inline,C,Performance,Inline,我有一个简单的函数,它将两个矩阵相乘 void mmul1(float A[ni][nk], float B[nk][nj], float C[ni][nj]) { int i, j, k; for (i=0; i<ni; i++) { for (j=0; j<nj; j++) { C[i][j] = 0; for (k=0; k<nk; k++) { C[i][j]
void mmul1(float A[ni][nk], float B[nk][nj], float C[ni][nj])
{
int i, j, k;
for (i=0; i<ni; i++) {
for (j=0; j<nj; j++) {
C[i][j] = 0;
for (k=0; k<nk; k++) {
C[i][j] += A[i][k]*B[k][j];
}
}
}
}
void mmul1(浮点A[ni][nk]、浮点B[nk][nj]、浮点C[ni][nj])
{
int i,j,k;
对于(i=0;i由于您不使用main
中的结果,当您inline
函数时,优化器可以看到没有正在使用的副作用,并且可以自由删除所有矩阵乘法代码
您可以使用gcc
的-s
标志查看生成的汇编代码。矩阵是硬编码的还是从用户输入中派生出来的?如果是硬编码的,从用户输入中派生出来的行为是否相同?矩阵中填充rand()@MohitJain:这是个问题。如果我发布相关代码的objdump会有帮助吗?你能发布汇编程序输出(gcc-S)吗?虽然这确实是一种可能性——我在评论中提到过,但代码片段被严重省略了(很多…
),那么我们如何才能知道结果是未使用的?@Clifford我们将不得不等待,看看OP是否以及何时修复了这个问题。我同意。最明显的问题是指针别名。根据我的经验,您应该知道您是否可以强制编译器假定没有指针别名(例如,如果支持,请使用restrict
)在相关函数中添加调试检查(使用assert(.)
宏)以强制执行。这是数值分析代码的常见问题,因为它通常会聚集大型类似结构(即float
或double
的大n-dim数组)。如果无法强制执行,则可能需要两个版本的函数,并将别名检查用作开关。
int main(int argc, char** argv) {
// timer structs
struct timeval ts, te, td;
float tser, tpar, diff;
int i, j, k;
printf("matrix size : %d x %d x %d\n", ni, nj, nk);
srand(0);
// initialization
for (i=0; i<ni; i++) {
for (k=0; k<nk; k++) {
A[i][k] = (float)rand()/RAND_MAX;
}
}
for (k=0; k<nk; k++) {
for (j=0; j<nj; j++) {
B[k][j] = (float)rand()/RAND_MAX;
}
}
gettimeofday(&ts, NULL);
for (i=0; i<ni; i++) {
for (j=0; j<nj; j++) {
Cans[i][j] = 0;
for (k=0; k<nk; k++) {
Cans[i][j] += A[i][k]*B[k][j];
}
}
}
gettimeofday(&te, NULL);
timersub(&ts, &te, &td);
tser = fabs(td.tv_sec+(float)td.tv_usec/1000000.0);
gettimeofday(&ts, NULL);
mmul1(A, B, C);
gettimeofday(&te, NULL);
timersub(&ts, &te, &td);
tpar = fabs(td.tv_sec+(float)td.tv_usec/1000000.0);
// compare results
diff = compute_diff(C, Cans);
printf("Performance : %.2f GFlop/s (%.1fX)\n", 2.0*ni*nj*nk/tpar/1000000000, tser/tpar );
printf("Result Diff : %.3f\n", diff );
return 0;
}