【问题标题】:Infinite parallel while loop无限并行while循环
【发布时间】:2021-05-06 23:22:51
【问题描述】:

我需要在 C# (MaxDegreeOfParallelism = Environment.ProcessorCount) 中并行调用相同的方法。该方法返回一个数字序列。如果此序列满足某些条件 - 我需要执行以下操作

  1. 停止所有线程
  2. 返回序列
  3. 返回该方法总共被调用了多少次

我有以下代码 - 但我在弄清楚在我写的 GetValidSequenze 方法中写什么时遇到了一些问题://WHAT TO DO HERE??

有什么想法吗?我做错了吗?

public class Example3
{
    public delegate int Randomizer(int minValue, int maxValue);

    private Randomizer rand;

    public Example3(Randomizer randomizer)
    {
        rand = randomizer;

    }
    private IEnumerable<bool> Infinite()
    {
        while (true)
        {
            yield return true;
        }
    }

    public int[][] GetValidSequenze(int minValue, int maxValue, int rows,
        int columns, int sn, ref int counter)
    {
        ParallelOptions op = new ParallelOptions();
        op.MaxDegreeOfParallelism = Environment.ProcessorCount;
        int[][] result;

        Parallel.ForEach(Infinite(), parallelOptions: op //WHAT TO DO HERE?? =>
        {
            int[][] tempRes;
            while (!(tempRes = GetSequenze(minValue, maxValue, rows, columns))
                .All(o => o.Contains(sn)))
            {
                Interlocked.Increment(ref counter);
            }
            loopState.Stop();
            result = tempRes;
        });

        return result;
    }

    public int[][] GetSequenze(int minValue, int maxValue, int rows, int columns)
    {
        int[][] lot = new int[rows][];
        for (int i = 0; i < rows; i++)
        {
            int[] column = new int[columns];
            for (int j = 0; j < columns; j++)
            {
                while (true)
                {
                    int tempNo = rand(0, 40);
                    if (!column.Contains(tempNo))
                    {
                        column[j] = tempNo;
                        break;
                    }
                }
            }
            lot[i] = column;
        }
        return lot;
    }
}

【问题讨论】:

  • 列数是 42 怎么办?
  • 我不明白你在问什么。 docs.microsoft.com/en-us/dotnet/api/… "Generally, you do not need to modify this setting." MSDN指出系统应该自动处理MaxDegreeOfParallelism
  • 对于指定我应该将 MaxDegreeOfParallelism 设置为处理器计数的分配。
  • @NateW 实际上文档给出的建议不是很好。如果您没有明确指定MaxDegreeOfParallelism,它将保持其默认值-1,这意味着无限并行。这将导致ThreadPool 立即饱和,并保持饱和状态直到源可枚举完成。如果您还有其他并发操作并行发生,这将是一个坏消息,例如System.Timers.Timer:它的Elapsed 事件将开始忙碌且零星地触发。这是一种不良行为,后续的 PLINQ 库没有模仿。
  • @TheodorZoulias 有趣。我不知道。我明白你的观点,在某些情况下,人们希望限制这一点,超出文档指出的范围。有任何文章/SO q 为其他人的利益而写,可以为我指明进一步阅读您所谈论的内容的方向?

标签: c# while-loop parallel-processing parallel.foreach


【解决方案1】:

您的代码无法编译。下面是编译的GetValidSequenze 方法的版本:

public int[][] GetValidSequenze(int minValue, int maxValue, int rows,
    int columns, int sn, ref int counter)
{
    int localCounter = counter;
    ParallelOptions op = new ParallelOptions();
    op.MaxDegreeOfParallelism = Environment.ProcessorCount;
    int[][] result = default;

    Parallel.ForEach(Infinite(), parallelOptions: op, (_, loopState) =>
    {
        int[][] tempRes;
        while (!(tempRes = GetSequenze(minValue, maxValue, rows, columns))
            .All(o => o.Contains(sn)))
        {
            Interlocked.Increment(ref localCounter);
        }
        loopState.Stop();
        result = tempRes;
    });

    counter = localCounter;
    return result;
}

有可能无论你想做什么,通过改进算法都可以更有效地完成,而不是通过并行化可能效率低下的算法。

【讨论】:

  • 感谢您的意见。这是一个作业,我需要使用并行性。
【解决方案2】:

定义一个您计划在满足条件时设置的变量。

bool criteriaMet = false;

遇到时设置。

修改你的枚举器:

private IEnumerable<bool> Infinite()
{
    while (!criteriaMet)
    {
        yield return true;
    }
}

如果您发现Infinite() 方法未检测到criteriaMet 中的任何更改,则可能是由于编译器优化所致。如果是这种情况,您可能需要使用 volatile 关键字,或者(更好)使用 CancellationToken 而不是 bool

【讨论】:

  • Parallel.ForEach 默认采用块分区,这意味着每个工作线程逐渐从源可枚举中获取越来越多的元素。因此,您通过终止可枚举来停止循环的建议很可能会导致并行循环的延迟终止。要禁用块分区,您需要提供一个有点尴尬的分区器:Partitioner.Create(Infinite(), EnumerablePartitionerOptions.NoBuffering)
猜你喜欢
  • 2015-06-25
  • 2014-03-29
  • 2016-08-27
  • 2011-09-26
  • 2015-04-29
  • 2014-05-30
  • 2017-10-12
  • 2020-11-30
  • 2015-05-22
相关资源
最近更新 更多