- 主题:用C++和C#测试,lambda的开销还是比较明显
循环1亿次进行double类型的累加计算:
double run(int n, function<double(double, double) > f)
{
double s = 0;
for (int i = 0; i < n; ++i)
s = f(s, i); //s +=i;
return s;
}
1、循环中直接计算,c#和c++都耗时0.14秒左右
2、循环中调用静态函数计算,c#和c++都耗时0.14秒左右,函数调用被内联优化了,没有开销
3、循环中调用lambda或函数指针,c#和c++都耗时0.29秒左右,函数调用开销明显。
结论:
1、这个场景下C++和C# 性能基本一样,没有区别。
2、lambda和函数指针无法被内联优化,代价相对较高,不宜在小粒度+大量循环中使用。
如果2是真实的,那么标准库和boost的函数式编程中大量使用到lambda、functor和函数指针
将明显影响对规模较大的容器的计算效率,这时候直接用循环效率更高。
测试环境:msvc143, dotnet6
--
FROM 123.112.71.*
又试了下神奇的numba
@jit
def run():
s=0.0
for i in range(100000000):
s+=i
return s
竟然只要0.155秒,比c++只有10%的差距
而不用numba,则需要7秒钟,使用lambda,需要17秒
【 在 finlab 的大作中提到: 】
: 循环1亿次进行double类型的累加计算:
: double run(int n, function<double(double, double) > f)
: {
: ...................
--
FROM 123.112.71.*
因为numba不支持对 lambda加速,所以使用lambda的版本耗时17秒。
又试了调用@jit函数的版本
@jit
def f(a,b):
return a+b
@jit
def run2(ff):
s=0.0
for i in range(100000000):
s=ff(s,i)
return s
for i in range(100):
t1=time()
s=run2(f)
t2=time()
print(t2-t1)
竟然只要0.18秒, 比C++版本还快很多。
看来numba的jit编译对于函数指针有优化。
【 在 finlab 的大作中提到: 】
: 又试了下神奇的numba
: @jit
: def run():
: ...................
--
FROM 123.112.71.*
release, 默认是O2的
【 在 foliver 的大作中提到: 】
: 开O2,lambda肯定会被优化。
: 你确定开O2了么?
--
FROM 123.112.71.*
@njit(parallel=True,fastmath=True)
def run2(ff):
s=0.0
for i in prange(100000000):
s +=i;
return s
开启并行和快速算术运算选响,尽然只要0.015秒,比c++的还快一个数量级。
当然c++版也可以并行,但是numba方便太多了。
还有一个simd的支持,我还没有搞定,如果能使用avx2,还能快很多。
【 在 finlab 的大作中提到: 】
: 因为numba不支持对 lambda加速,所以使用lambda的版本耗时17秒。
: 又试了调用@jit函数的版本
: @jit
: ...................
--
FROM 123.112.71.*
激活svml(avx2)后,只要0.006秒了。
从一开始C++的单线程0.14秒,到python numba(i5 8265u,4c8t,avx2)的0.006秒,
理论最高加速8*4=32倍,实际加速23倍。
numba太牛了,可以几乎不用做什么工作,就能同时发挥多现场和simd的威力
这样完全可以胜任cpu密集的工作了
【 在 finlab 的大作中提到: 】
: @njit(parallel=True,fastmath=True)
: def run2(ff):
: s=0.0
: ...................
--
修改:finlab FROM 123.112.71.*
FROM 123.112.71.*
嗯,如果用模板传进来,应该可以内联掉
【 在 ziqin 的大作中提到: 】
: lambda不是你这么传的。用template
--
FROM 123.112.71.*
c++的0.14秒,是已经打开msvc的avx2编译选项的。
我对比过手动simd编程与编译器自动优化的结果,vc的simd优化效果不佳,不能充分发挥simd威力。
python的numba底层llmv,也是调用了icc_rt来充分利用simd加速。
但普通开发,除了专门数值计算的, 也没多少人用icc。
另外,这个0.14秒,也已经是内联优化掉,没有函数调用开销的耗时。
【 在 hyperLee 的大作中提到: 】
: 菜,你这是函数指针,不能算是lambda
: lambda你至少得用个模板
: 还有sse之类的,用intel编译器自动向量化就好了。
: ...................
--
FROM 123.112.71.*
大佬, 您的代码里循环次数是10**6, 我原来是10**8
而且我的python代码是s是double的,所以加法也是double的
您再跑下看看
我的机器上10**8是这样的:
OpenMP init.
Run0 resut is 4999999950000000.00, done in 339.596 ms!
Run1 resut is 4999999950000000.00, done in 141.213 ms!
Run2 resut is 4999999950000000.00, done in 125.127 ms!
Run3 resut is 4999999950000000.00, done in 120.397 ms!
Run4 resut is 4999999950000000.00, done in 129.667 ms!
Run5 resut is 4999999950000000.00, done in 29.3486 ms!
Run6 resut is 4999999950000000.00, done in 7.1298 ms!
您打开simd优化了吗? run5的 29ms应该最快的,run6是整型运算不可比。
【 在 ble 的大作中提到: 】
: 实际上你的C++都在做double加法,没法启用AVX;而Python代码都在做int加法,所以可以启用。
: #include <chrono>
: #include <format>
: ...................
【 在 ble 的大作中提到: 】
: 实际上你的C++都在做double加法,没法启用AVX;而Python代码都在做int加法,所以可以启用。
: #include <chrono>
: #include <format>
: ...................
--
FROM 123.112.71.*
AVX2支持各种整数和浮点数运算的, 256位,支持4路double并行
前面python里面也是浮点,不是整数
【 在 ble 的大作中提到: 】
: 实际上你的C++都在做double加法,没法启用AVX;而Python代码都在做int加法,所以可以启用。
: #include <chrono>
: #include <format>
: ...................
--
FROM 123.112.71.*