当前位置: 首页 > 编程语言 > C#

为什么在这种情况下使用AsParallel()比使用foreach慢?Share

时间:2023-04-11 10:57:08 C#

为什么在这种情况下使用AsParallel()比foreach慢?我正在以这种格式从excel中提取数据product1|unnamedcol2|product2|unnamedcol4|product3|unnamedcol6|------------------------------------------------------------------------------@1foo|1.10|@1foo|0.3|@1foo|0.3@2foo|1.00|@2foo|2|@2foo|@3foo|1.52|@3foo|2.53|@3foo|@4foo|1.47|||@4foo|1.31@5foo|1.49|||@5foo|1.31该文件使用了全部255个字段。使用dapper-dot-net我通过此代码获取数据IEnumerableexcelDataRaw=conn.Query(string.Format("select*from{0}",table)).Cast();我通过这些数据传递给这些测试方法。数据作为IDictionaries的IEnumerable返回,其中每个键是一个产品,每个值都是一个IDictionary,其中每个键是产品列中的一个值,对应的值是未命名列中产品列右侧的值。varexcelDataRefined=newList>();excelDataRefined.Add(newDictionary());excelDataRefined[0].Add("产品",newDictionary());excelDataRefined[0]["产品"].Add("@1foo",1.1m);方法:privatestaticDictionaryBenchmark_foreach(IEnumerableexcelDataRaw){Console.WriteLine("1.Usingforeach");varwatch=new秒表();观看。开始();列表标题=excelDataRaw.Select(dictionary=>dictionary.Keys).First().ToList();boolisEven=false;列出产品=headers.Where(h=>isEven=!isEven).ToList();vardates=newList();varprices=newList();foreach(标头中的字符串字段){stringproduct1=field;如果(headers.IndexOf(field)%2==0){dates.Add(excelDataRaw.AsParallel().AsOrdered().Select(col=>col[product1]).Where(row=>row!=null));}如果(headers.IndexOf(fi场)%2==1){prices.Add(excelDataRaw.AsParallel()。AsOrdered()。选择(col=>col[product1]??0m)。Take(dates.Last()。Count()));}}watch.Stop();Console.WriteLine("重新排列数据:{0}s",watch.Elapsed.TotalSeconds);观看.重启();varexcelDataRefined=newDictionary();foreach(日期中的IEnumerable日期列表){十进制数;IEnumerable日期列表1=日期列表;IEnumerablepricelist=prices[dates.IndexOf(datelist1)].Select(value=>value??0m).Where(content=>decimal.TryParse(content.ToString(),outnum));Dictionarydict=datelist1.Zip(pricelist,(k,v)=>new{k,v}).ToDictionary(x=>(string)xk,x=>decimal.Parse(xvToString()));if(!excelDataRefined.ContainsKey(products[dates.IndexOf(datelist1)])){excelDataRefined.Add(products[dates.IndexOf(datelist1)],dict);}}watch.Stop();Console.WriteLine("压缩数据:{0}s",watch.Elapsed.TotalSeconds);返回excelDataRefined;}privatestaticDictionaryBenchmark_AsParallel(IEnumerableexcelDataRaw){Console.WriteLine("2.使用AsParallel().AsOrdered().ForAll");varwatch=new秒表();观看。开始();列表标题=excelDataRaw.Select(dictionary=>dictionary.Keys).First().ToList();boolisEven=false;列出产品=headers.Where(h=>isEven=!isEven).ToList();vardates=newList();varprices=newList();headers.AsParallel().AsOrdered().ForAll(field=>dates.Add(excelDataRaw.AsParallel().AsOrdered().TakeWhile(x=>headers.IndexOf(field)%2==0).Select(列=>col[field]).Where(row=>row!=null).ToList()));headers.AsParallel().AsOrdered().ForAll(field=>prices.Add(excelDataRaw.AsParallel().AsOrdered().TakeWhile(x=>headers.IndexOf(field)%2==1).Select(col=>col[field]??0m).Take(256).ToList()));dates.RemoveAll(x=>x.Count()==0);prices.RemoveAll(x=>x.Count()==0);观看。停止();Console.WriteLine("重新排列数据:{0}s",watch.Elapsed.TotalSeconds);观看.重启();varexcelDataRefined=newDictionary();foreach(日期中的IEnumerable日期列表){十进制数;IEnumerable日期列表1=日期列表;IEnumerablepricelist=prices[dates.IndexOf(datelist1)].Select(value=>value??0m).Where(content=>decimal.TryParse(content.ToString(),outnum));Dictionarydict=datelist1.Zip(pricelist,(k,v)=>new{k,v}).ToDictionary(x=>(string)xk,x=>decimal.Parse(xvToString()));if(!excelDataRefined.ContainsKey(products[dates.IndexOf(datelist1)])){excelDataRefined.Add(products[dates.IndexOf(datelist1)],dict);}}watch.Stop();Console.WriteLine("压缩数据:{0}s",watch.Elapsed.TotalSeconds);返回excelDataRefined;}privatestaticDictionaryBenchmark_ForEach(IEnumerableexcelDataRaw){Console.WriteLine("3.使用ForEach");varwatch=new秒表();观看。开始();列表标题=excelDataRaw.Select(dictionary=>dictionary.Keys).First().ToList();boolisEven=false;列出产品=headers.Where(h=>isEven=!isEven).ToList();vardates=newList();varprices=newList();headers.ForEach(字段=>dates.Add(excelDataRaw.TakeWhile(x=>headers.IndexOf(field)%2==0).Select(col=>col[field]).Where(row=>row!=null).ToList()));headers.ForEach(field=>prices.Add(excelDataRaw.TakeWhile(x=>headers.IndexOf(field)%2==1).Select(col=>col[field]??0m).Take(256).ToList()));dates.RemoveAll(x=>x.Count()==0);prices.RemoveAll(x=>x.Count()==0);观看。停止();Console.WriteLine("重新排列数据:{0}s",watch.Elapsed.TotalSeconds);观看.重启();varexcelDataRefined=newDictionary<字符串,IDictionary>();foreach(日期中的IEnumerable日期列表){十进制数;IEnumerable日期列表1=日期列表;IEnumerablepricelist=prices[dates.IndexOf(datelist1)].Select(value=>value??0m).Where(content=>decimal.TryParse(content.ToString(),outnum));Dictionarydict=datelist1.Zip(pricelist,(k,v)=>new{k,v}).ToDictionary(x=>(string)xk,x=>decimal.Parse(xvToString()));if(!excelDataRefined.ContainsKey(products[dates.IndexOf(datelist1)])){excelDataRefined.Add(products[dates.IndexOf(datelist1)],dict);}}watch.Stop();Console.WriteLine("压缩数据:{0}s",watch.Elapsed.TotalSeconds);返回excelDataRefined;为什么它会这样?我希望AsParallel是最快的,因为它是并行执行的,而不是顺序执行的。我该如何优化它?为了实现并行计算,你必须有多个处理器或核心,否则你只是在线程池中排队等待CPU的任务。即单核机器上的AsParallel是顺序加上线程池和线程上下文切换的开销。即使在双核机器上,也可能无法获得两个内核,因为许多其他东西都在同一台机器上运行。实际上.AsParallel()只有在您有长时间运行的阻塞操作(I/O)任务时才有用,操作系统可以挂起阻塞线程并让另一个线程运行。创建额外的线程和管理每个线程的工作负载会产生开销。