【发布时间】:2018-12-21 01:32:37
【问题描述】:
我正在优化一个简单的遗传算法和神经网络,我正在修改 GCC 中的一些选项以生成更快的可执行文件。
在我的代码中我有一些断言,例如
mat mat_add(mat a, mat b)
{
assert(a->rows == b->rows);
assert(a->cols == b->cols);
mat m = mat_create(a->rows, a->cols);
for(size_t i = 0; i < a->rows; i++) {
for(size_t j = 0; j < a->cols; j++)
mat_set(m, i, j, mat_get(a, i, j) + mat_get(b, i, j));
}
return m;
}
我想如果我添加-DNDEBUG 来禁用断言,可执行文件会更快,因为它不会检查上述条件。但是,它实际上更慢。
没有-DNDEBUG:
$ gcc src/*.c -lm -pthread -Iinclude/ -Wall -Ofast
$ for i in $(seq 1 5); do time ./a.out; done
real 0m11.677s
user 1m28.786s
sys 0m0.729s
real 0m11.716s
user 1m29.304s
sys 0m0.723s
real 0m12.217s
user 1m31.707s
sys 0m0.806s
real 0m12.602s
user 1m32.863s
sys 0m0.726s
real 0m12.225s
user 1m30.915s
sys 0m0.736s
与-DNDEBUG:
$ gcc src/*.c -lm -pthread -Iinclude/ -Wall -Ofast -DNDEBUG
$ for i in $(seq 1 5); do time ./a.out; done
real 0m13.698s
user 1m42.533s
sys 0m0.792s
real 0m13.764s
user 1m43.337s
sys 0m0.709s
real 0m13.655s
user 1m42.986s
sys 0m0.739s
real 0m13.836s
user 1m43.138s
sys 0m0.719s
real 0m14.072s
user 1m43.879s
sys 0m0.712s
速度并不慢,但很明显。
什么可能导致这种放缓?
【问题讨论】:
-
我不知道答案,但您是否尝试创建
size_t arows = a->rows和size_t brows = b->rows的本地副本。我已经看到这是一种可能的优化,因为循环不必一直通过指针间接检查值。 (毕竟,它们可以在其他线程中被更改。)也许断言正在帮助编译器创建这两个的有效本地副本。 -
@alfC 我试过你的建议,性能确实提高了大约 0.5 秒。我想知道为什么在使用断言时可以优化指针间接,因为在这些断言之后值仍然可以改变。
-
这不能回答您的问题,但
mat_get和mat_set的定义是否在同一个翻译单元中可见(例如,标题中的内联函数)?如果没有,你就是在浪费时间用优化标志来追逐微小的收益(并且冒着破坏事情的风险,因为-Ofast执行无效的转换)并且应该使它们内联,或者更好的是,摆脱访问器函数并使用二维数组直接地。这可能会产生一个数量级的差异。 -
@Demindiro,我不是专家,但我认为
-Ofast可以进行非法律优化,而这本身就会使您陷入疯狂的境地。你用-O3测试了吗?也许到那时它会有意义,即使你的整体运行时间会变慢。 -
检查生成的代码,你就会有答案。猜测是没有意义的
标签: c gcc optimization