今天又折腾了会C#。
先是使用PLINQ的Aggrigate, 需要0.9秒,而没有并行的Aggrigate只要0.6-0.7秒。
Range(0.0,10000_0000).AsParallel().Sum();
虽然写起来非常简单,但是性能非常不理想。LINQ只能用在大执行粒度或者性能不敏感的地方。
然后用并行循环:
public static double run_pfor()
{
ConcurrentBag<double> bag= new ConcurrentBag<double>();
int n = 10000_0000;
Parallel.ForEach(Partitioner.Create(0,n , n/8+1),
(range) => {
double s = 0;
for (int i = range.Item1; i <range.Item2; i++)
s += i;
bag.Add(s);
});
return bag.Sum();
}
自己写并行循环的速度提升很多,从单线程的0.14秒,提升到0.016秒,
接近于c++的0.014秒,基本发挥了多线程的作用。
但是,与python+numba的0.006秒还是差不少。这个差别是dotnet编译器和jit都不会进行simd优化。
只有开发者主动写了simd代码才能使用simd指令。这个很让人失望。
VC++也基本没有发挥simd的作用,不过前面帖子的gcc的simd优化效果很好。
最后的pk,python+numba(llvm、openmp、icc_rt)最快,不过numba编程时不能使用python对象,这是一个很大的限制。
最后,再罗列下C++,C#,Python的耗时:
简单循环:0.14, 0.14, 8秒
加速后:0.014, 0.016, 0.006秒
编程方面,python+numba,c++openmp 都是自动并行化,不需要改变代码逻辑,工作量很小
而c# 缺乏自动并行和向量化,需要手动实现,工作量最大。
【 在 finlab 的大作中提到: 】
: 循环1亿次进行double类型的累加计算:
: double run(int n, function<double(double, double) > f)
: {
: ...................
--
FROM 123.112.71.*