c# - ParallelEnumerable.Zip() 是如何工作的,为什么调用 AsEnumerable() 时行为会发生变化?
问题描述
我试图了解与andParallelEnumerable.Zip()
结合使用的行为。IEnumerable<T>
AsEnumerable()
给定下面的代码parallelResult
andresult
将不一样。假设ParallelEnumerable.Zip()
意味着我只想随机配对项目,这是有道理的。但是,如果我取消注释AsEnumerable()
,则parallelResult.ShouldBe(result)
不再抛出,即使是非常大n
且重复的运行。如果两个输入都是List
s,则断言也通过。
预期的行为是什么?我们在调用时是否依赖于实现细节AsEnumerable()
?
int n = 200;
IReadOnlyList<double> list = Enumerable.Range(0, n).Select(x=>(double)x).ToList();
IEnumerable<double> enumerable = Enumerable.Range(10, n).Select(x => (double)x);
var result = list
.Zip(enumerable, Tuple.Create)
.OrderBy(x=>x.Item1)
.ThenBy(x=>x.Item2)
.ToList();
var parallelResult = list
.AsParallel()
.Zip(enumerable.AsParallel(), Tuple.Create)
// .AsEnumerable()
.OrderBy(x => x.Item1)
.ThenBy(x => x.Item2)
.ToList();
parallelResult.ShouldBe(result);
解决方案
正如 NetMage 指出的PLINQ 文档中关于排序状态的文档,该文档Zip()
属于组中的运算符“以下 PLINQ 查询运算符在某些情况下可能需要有序的源序列才能产生正确的结果: ”。
因此AsOrdered()
,如果代码多次运行,则必须使用它来保证每对中都有相同的项目。要获得有序结果,上面的示例必须如下所示
int n = 200;
IReadOnlyList<double> list = Enumerable.Range(0, n).Select(x=>(double)x).ToList();
IEnumerable<double> enumerable = Enumerable.Range(10, n).Select(x => (double)x);
var result = list
.Zip(enumerable, Tuple.Create)
.OrderBy(x=>x.Item1)
.ThenBy(x=>x.Item2)
.ToList();
var parallelResult = list
.AsParallel()
.AsOrdered()
.Zip(enumerable.AsParallel().AsOrdered(), Tuple.Create)
.OrderBy(x => x.Item1)
.ThenBy(x => x.Item2)
.ToList();
parallelResult.ShouldBe(result);
所有其他看似可重复结果的情况只是巧合,或者是由于实施细节可能发生变化。
推荐阅读
- javascript - canvas.toDataURL() 返回“不是函数”
- boost - 如何从 boost UDP 服务器读取数据
- mysql - MySQL中同一张表的共同值
- angular - 设置没有焦点的错误状态时,Angular Material MatChipList MatError 不可见
- visual-studio-code - VSCode 中的红色文件夹图标
- sql - postgresql 中的子句“临时表”与“全局临时表”有什么区别?
- bokeh - 如何使用 Bokeh 和 Holoview(例如在标题或颜色栏中)在字符串中“轻松”插入 unicode 符号(上标、度数等)?
- angular - “没有可用于给定请求的身份验证功能”保管箱角度
- java - E/OpenCV/StaticHelper:OpenCV 错误:无法为 OpenCV 加载信息库
- git - 删除 git 分支历史