如何在Parallel.ForEach中迭代多个span-s ?



输入代码:

代码:

for (int i4 = 0; i4 < ba_result_out.Length; i4 += c.i_key_size)
{
k = BitConverter.ToInt64(spn_data.Slice(i4, c.i_key_size));
if (Dictionary.md1.ContainsKey(k)) { 
//some logics skipped
}
}

代码我试图做:(基于:https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-speed-up-small-loop-bodies)

ParallelOptions po = new ParallelOptions { MaxDegreeOfParallelism = 2 };
var rp = Partitioner.Create(0, ba_result_out.Length / c.i_key_size, po.MaxDegreeOfParallelism);
Parallel.ForEach(rp, po, (range, loopState) =>
{
for (int i4 = range.Item1; i4 < range.Item2; i++)
{
k = BitConverter.ToInt64(spn_data.Slice(i4, c.i_key_size));
if(Dictionary.ContainsKey(k)){
//some logics skipped
}
});

task:设置为Parallel。

问题:编译器不允许在lambda

中使用span是否有可能通过多个跨度并行循环每个跨度?

的被害者。这是非常热的代码-数十亿次迭代-所以分配不是一个选项-需要坚持使用span。

感谢所有参与的人!

我使它按预期工作,使用AsSpan()内部lambda函数:

  1. 我切换到人工数组索引代替跨度作为基础的PFE
  2. 我在lambda中使用了1个Span分配(因为整个索引是按分区中的核数分配的,所以只分配了4个Span)
  3. 这是一个实现从MS小体循环并行化(链接我的原始帖子)
  4. 可以进一步改进,通过将指针传递给span,从而避免这里提到的分配

我最后得到了这个:

i_max_search_threads = 4;
int[] ia_base_idxs = Enumerable.Range(0, ba_result_out.Length).ToArray();
var rp = Partitioner.Create(0, ia_base_idxs.Length, ia_base_idxs.Length / i_max_search_threads);
Parallel.ForEach(rp, po, (range, loopState) =>
{
Span<byte> spn_data = ba_result_out.AsSpan();
for (int i4 = range.Item1; i4 < range.Item2; i4 += c.i_key_size)
{
k = BitConverter.ToInt64(spn_data.Slice(i4, c.i_key_size));
if(Dictionary.ContainsKey(k)){
//some logics skipped...
}
}
});

最新更新