c - 为什么函数式代码比 C 中的命令式代码快得多?
问题描述
我一直在研究一种算法,用于计算各种语言中表达式的最大深度(即有多少嵌套括号),只是为了好玩/练习。
我注意到函数式 C 代码和命令式 C 代码的性能存在巨大的性能差异,我想知道为什么会这样。
给定字符串“(1+(2*3)+((8)/4))+1”,命令式代码在大约 10-13us 内始终如一地完成,但功能性代码需要 2-3us,快两倍多。这两种算法都是用-O2
和 gcc 编译的,所以我发现这非常令人惊讶,但我对编译器的实现知之甚少,无法理解为什么。
那么谁能告诉我为什么功能代码的速度如此之快?
功能代码(注意 _ERR 的东西只是带有整数的#define):
const int max_depth_functional(
const char *expr, const int sum, const int max) {
switch(*expr) {
case '\0':
return sum == 0 ? max : UNTERM_PARENTH_ERR;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '+': case '-': case '*': case '/': case '^':
return max_depth_functional(expr + 1, sum, max);
case '(':
return max_depth_functional(
expr + 1, sum + 1, sum + 1 > max ? sum + 1 : max
);
case ')':
return max_depth_functional(expr + 1, sum - 1, max);
default:
return INVALID_EXPR_ERR;
}
}
命令式代码:
const int max_depth_imperative(const char *expr) {
int curr_sum = 0, curr_max = 0;
while(*expr != '\0') {
switch(*expr++) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '+': case '-': case '*': case '/': case '^':
break;
case '(':
curr_sum++;
curr_max = curr_sum > curr_max ? curr_sum : curr_max;
break;
case ')':
curr_sum--;
break;
default:
return INVALID_EXPR_ERR;
}
}
return curr_sum == 0 ? curr_max : UNTERM_PARENTH_ERR;
}
两者都被称为:
const clock_t start = clock();
const int func_result = max_depth_func(args[1]);
const clock_t end = clock();
另外,我正在使用 Linux x86_64 来构建和运行
解决方案
根据评论,我使用以下方法运行代码:
double imperative_time_sum = 0, functional_sum_time = 0;
for(int i = 0; i < 100000; i++) {
const clock_t start_imp = clock();
max_depth(args[1]);
const clock_t end_imp = clock();
max_depth_functional_fast(args[1], 0, 0);
const clock_t end_func = clock();
imperative_time_sum +=
1000 * (double) (end_imp - start_imp) / CLOCKS_PER_SEC;
functional_sum_time +=
1000 * (double) (end_func - end_imp) / CLOCKS_PER_SEC;
}
printf("Average imperative: %fms\n", imperative_time_sum / 100000);
printf("Average functional: %fms\n", functional_sum_time / 100000);
产生的结果:
Average imperative: 0.002412ms
Average functional: 0.002421ms
尽管我之前重新运行了该程序超过 100 次,但我没有运行接近 100000 次。在那之后,时代非常接近。
推荐阅读
- python - 将csv文件动态加载到熊猫
- java - Weblogic 服务器 - 无法转换为内部表示:weblogic.jdbc.wrapper.Blob_oracle_sql_BLOB@3
- python-3.x - 如何将pycharm中的python从3.8降级到3.7(我正在尝试运行Tensorflow)
- sql-server - 如何指定具有集成安全性的用户 ID/密码?
- ios - 有没有办法计算金属纹理在分配之前使用了多少内存?
- javascript - 如何从客户端修改存储在服务器上的 .JSON 文件?
- reactjs - ReactJS 在异步条件之前渲染组件
- python - Pandas:按自定义函数对数据框进行分组
- javascript - 当它已经设置时更改它的属性值
- python - 带有 python 头的 Pipenv