IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原].Net 中Partitioner static与dynamic的性能对比

    csharp25发表于 2015-12-14 17:40:05
    love 0

    先看LINQ的方式,dynamic的方式:

    void Main()
    {
    	// testing setup
    	var source = Enumerable.Range(0, 10000000).ToArray();
    	double[] results = new double[source.Length];
    	
    	Console.WriteLine("creating partitioner in LINQ way...");
    	var dt = DateTime.Now;
    	var partitionerLinq = Partitioner.Create(source, true);
    	Console.WriteLine("creating partitioner in LINQ done, ticks: " + (DateTime.Now - dt).Ticks);
    	
    	dt = DateTime.Now;
    	var r = partitionerLinq.AsParallel().Select(x => x * x * Math.PI).ToList();
    	Console.WriteLine("LINQ way done , ticks:" + (DateTime.Now - dt).Ticks);
    	
    
    
    	dt =  DateTime.Now;
    
    
    	for(var i = 0;i < source.Length; i++){
    		results[i] = source[i] * Math.PI;
    	}
    	
    	Console.WriteLine("processing by single thread done, ticks : " + (DateTime.Now - dt).Ticks);
    }




    LINQPAD输出:
    creating partitioner in LINQ way...
    creating partitioner in LINQ done, ticks: 0
    LINQ way done , ticks:3472754
    processing by single thread done, ticks : 380298


    可见,动态分配chunk的partition基本比单线程的普通实现慢了10倍!


    再看静态的方式:

    void Main()
    {
    	// testing setup
    	var source = Enumerable.Range(0, 10000000).ToArray();
    	double[] results = new double[source.Length];
    	
    	Console.WriteLine("creating partitioner in a way processing as static range ..");
    	var dt = DateTime.Now;
    	// Partition the entire source array.
    	var rangePartitioner = Partitioner.Create(0, source.Length);
    	
    	Console.WriteLine("created partitioner, ticks:" + (DateTime.Now - dt).Ticks);
    
    
    	dt =  DateTime.Now;
    	// Loop over the partitions in parallel.
    	Parallel.ForEach(rangePartitioner, (range, loopState) =>
    	{
    		// Loop over each range element without a delegate invocation.
    		for (int i = range.Item1; i < range.Item2; i++)
    		{
    			results[i] = source[i] * source[i] * Math.PI;
    		}
    	});
    	Console.WriteLine("processing by range partitioner done, ticks : " + (DateTime.Now - dt).Ticks);
    	
    	dt =  DateTime.Now;
    
    
    	for(var i = 0;i < source.Length; i++){
    		results[i] = source[i] * Math.PI;
    	}
    	
    	Console.WriteLine("processing by single thread done, ticks : " + (DateTime.Now - dt).Ticks);
    }
    
    
    // Define other methods and classes here
    




    LINQPAD输出:

    creating partitioner in a way processing as static range ..
    created partitioner, ticks:0
    processing by range partitioner done, ticks : 185180
    processing by single thread done, ticks : 375279


    基本上,静态partition的方式比普通方式快两倍。


    现在,依然使用静态方式,把数据量增大10倍,看LINQ输出:

    creating partitioner in a way processing as static range ..
    created partitioner, ticks:0
    processing by range partitioner done, ticks : 1951457
    processing by single thread done, ticks : 3808162




    可以看到,时间差别依然差不多是一倍的速度。




    总结,当考虑使用Partition时,最好使用静态方式;并且处理逻辑不建议过于复杂(MSDN建议:In general, range partitioning is only faster when the execution time of the delegate is small to moderate);不过这一点还有待测试,暂时没有想出合适的logic来测试。


沪ICP备19023445号-2号
友情链接