log 的不同实现带来的常数差距
  • 板块学术版
  • 楼主zymooll
  • 当前回复16
  • 已保存回复16
  • 发布时间2023/6/7 20:37
  • 上次更新2023/10/23 13:42:55
查看原帖
log 的不同实现带来的常数差距
289296
zymooll楼主2023/6/7 20:37

前言

本文的常数测试均在 Luogu IDE 中测试,测试 C++ 版本为 C++14(GCC 9)+O2,随机数生成种子为 114514,值域取 [0,108)[0,10^8) 的整数,以运行 1e7 次对数运算为准.

效率测试

函数第一次测试第二次测试第三次测试平均值内存开销
std::log2()40ms61ms61ms54.00ms696kb
std::__lg()60ms61ms60ms60.33ms684kb
递推161ms181ms162ms168.00ms196052kb

当值域降到 [0,106)[0,10^6) 的整数时

函数第一次测试第二次测试第三次测试平均值内存开销
std::log2()60ms61ms60ms60.33ms692kb
std::__lg()60ms60ms60ms60.00ms684kb
递推60ms61ms60ms60.33ms2388kb

降低值域的同时,将查询次数增加到 2e8 次.

函数第一次测试第二次测试第三次测试平均值内存开销
std::log2()1086ms1067ms1068ms1073.67ms692kb
std::__lg()1006ms1006ms1012ms1008.00ms808kb
递推1026ms1026ms1028ms1027.00ms2268kb

总结

综上所述,递推法在各类环境中很难起到作用,甚至会增加时空复杂度,而自带的库函数表现优秀,std::__lg() 在一定程度上优于 std::log2().

附录

测试代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn1=1e6;
const int maxn2=2e8;
int main(){
    srand(114514);
    for(int i=1;i<=maxn2;i++){
        int k=log2(rand()%maxn1);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn1=1e6;
const int maxn2=2e8;
int main(){
    srand(114514);
    for(int i=1;i<=maxn2;i++){
        int k=__lg(rand()%maxn1);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn1=1e6;
const int maxn2=2e8;
short lg[maxn1+10];
int main(){
    srand(114514);
    lg[2]=1;
    for(int i=1;i<=maxn1;i++){
        lg[i]=lg[i>>1]+1;
    }
    for(int i=1;i<=maxn2;i++){
        int k=lg[rand()%maxn1];
    }
    return 0;
}
2023/6/7 20:37
加载中...