步长大于 1 的数组并行迭代
Parallel iteration over array with step size greater than 1
我正在研究一个用于进行信念传播立体视觉的练习程序。这里的相关方面是我有一个相当长的数组代表图像中的每个像素,并且想要在数组的每次迭代中对数组中的每个 second 条目执行操作for 循环 - 第一个条目的一半,然后在下一次迭代中的另一半(这来自 Felzenswalb 和 Huttenlocher 在他们 2006 年的论文 'Efficient belief propagation for early vision' 中描述的优化。)因此,您可以将其视为具有外部 for 循环 运行s 多次,并且对于该循环的每次迭代,我迭代数组中一半的条目。
我想像这样并行化遍历数组的操作,因为我相信这样做是线程安全的,而且当然可能更快。该操作涉及更新表示相邻像素的数据结构内的值,这些相邻像素本身并未在外循环的给定迭代中使用。最初我只是一次性遍历整个数组,这意味着执行此操作相当简单 - 我需要做的就是将 .Parallel
放在 Array
和 .iteri
之间。但是,更改为对每个第二个数组条目进行操作比较棘手。
为了从简单地遍历每个条目进行更改,我从 Array.iteri (fun i p -> ...
改为使用 for i in startIndex..2..(ArrayLength - 1) do
,其中 startIndex 是 1 或 0,具体取决于我最后使用的是哪一个(通过切换 a布尔值)。这意味着虽然我不能简单地使用非常好的 .Parallel
来并行处理 运行。
我还没有找到任何关于如何在步长大于 1 的 .NET 中实现并行 for 循环的具体信息。我能找到的最好的是 a paragraph in an old MSDN document on parallel programming in .NET,但是那段只对在循环体内转换索引做了一个模糊的陈述。我不明白那里是什么意思。
我查看了 Parallel.For and Parallel.ForEach, as well as creating a custom partitioner,但其中 none 似乎包含更改步长的选项。
我想到的另一个选择是使用序列表达式,例如
let getOddOrEvenArrayEntries myarray oddOrEven =
seq {
let startingIndex =
if oddOrEven then
1
else
0
for i in startingIndex..2..(Array.length myarray- 1) do
yield (i, myarray.[i])
}
然后使用 ParallelSeq 中的 PSeq.iteri
,但我不确定它是否能与 .NET Core 2.2 一起正常工作。 (请注意,至少目前,我需要知道数组中给定元素的索引,因为它在处理过程中用作另一个数组的索引)。
如何并行遍历数组的每个第二个元素? IE。使用大于 1 的步长遍历数组?
您可以尝试 PSeq.mapi
,它不仅提供序列项作为参数,还提供项的索引。
这是一个小例子
let res = nums
|> PSeq.mapi(fun index item -> if index % 2 = 0 then item else item + 1)
你也可以看看这个sampling snippet。请务必将 Seq
替换为 PSeq
我正在研究一个用于进行信念传播立体视觉的练习程序。这里的相关方面是我有一个相当长的数组代表图像中的每个像素,并且想要在数组的每次迭代中对数组中的每个 second 条目执行操作for 循环 - 第一个条目的一半,然后在下一次迭代中的另一半(这来自 Felzenswalb 和 Huttenlocher 在他们 2006 年的论文 'Efficient belief propagation for early vision' 中描述的优化。)因此,您可以将其视为具有外部 for 循环 运行s 多次,并且对于该循环的每次迭代,我迭代数组中一半的条目。
我想像这样并行化遍历数组的操作,因为我相信这样做是线程安全的,而且当然可能更快。该操作涉及更新表示相邻像素的数据结构内的值,这些相邻像素本身并未在外循环的给定迭代中使用。最初我只是一次性遍历整个数组,这意味着执行此操作相当简单 - 我需要做的就是将 .Parallel
放在 Array
和 .iteri
之间。但是,更改为对每个第二个数组条目进行操作比较棘手。
为了从简单地遍历每个条目进行更改,我从 Array.iteri (fun i p -> ...
改为使用 for i in startIndex..2..(ArrayLength - 1) do
,其中 startIndex 是 1 或 0,具体取决于我最后使用的是哪一个(通过切换 a布尔值)。这意味着虽然我不能简单地使用非常好的 .Parallel
来并行处理 运行。
我还没有找到任何关于如何在步长大于 1 的 .NET 中实现并行 for 循环的具体信息。我能找到的最好的是 a paragraph in an old MSDN document on parallel programming in .NET,但是那段只对在循环体内转换索引做了一个模糊的陈述。我不明白那里是什么意思。
我查看了 Parallel.For and Parallel.ForEach, as well as creating a custom partitioner,但其中 none 似乎包含更改步长的选项。
我想到的另一个选择是使用序列表达式,例如
let getOddOrEvenArrayEntries myarray oddOrEven =
seq {
let startingIndex =
if oddOrEven then
1
else
0
for i in startingIndex..2..(Array.length myarray- 1) do
yield (i, myarray.[i])
}
然后使用 ParallelSeq 中的 PSeq.iteri
,但我不确定它是否能与 .NET Core 2.2 一起正常工作。 (请注意,至少目前,我需要知道数组中给定元素的索引,因为它在处理过程中用作另一个数组的索引)。
如何并行遍历数组的每个第二个元素? IE。使用大于 1 的步长遍历数组?
您可以尝试 PSeq.mapi
,它不仅提供序列项作为参数,还提供项的索引。
这是一个小例子
let res = nums
|> PSeq.mapi(fun index item -> if index % 2 = 0 then item else item + 1)
你也可以看看这个sampling snippet。请务必将 Seq
替换为 PSeq