简体   繁体   English

对 C# 中的 Parallel.ForEach 循环感到困惑

[英]Confused with the Parallel.ForEach loop in C#

I'm new to C# and am basically trying to generate large Integers using the BigInteger class in C#, by feeding it a byte[] array of randomly filled values.我是 C# 的新手,基本上是在尝试使用 C# 中的 BigInteger 类生成大整数,方法是为其提供一个随机填充值的 byte[] 数组。 I have another method, CheckForPrime(BigIngeger b) that checks for a prime number and simply returns true if the number is prime.我有另一种方法CheckForPrime(BigIngeger b)检查素数,如果该数是素数则简单地返回 true。 So to run everything, I'm using a Parallel ForEach loop which loops infinitely until a condition is false.因此,为了运行所有内容,我使用了一个 Parallel ForEach 循环,该循环无限循环,直到条件为假。 Here is my code:这是我的代码:

private static IEnumerable<bool> IterateUntilFalse(bool condition)
{
    while (condition) yield return true;
}

and here is my attempt at a Parallel.ForEach loop that runs till the condition is false:这是我对 Parallel.ForEach 循环的尝试,该循环一直运行到条件为假:

public void PrintOutPrimes(int numPrimes)
{
    byte[] makeBytes = new byte[512];
    BigInteger makePrime;
    RandomNumberGenerator r = RandomNumberGenerator.Create();
    ConcurrentBag<BigInteger> bbag = new ConcurrentBag<BigInteger>();

    int trackNum = 0;
    bool condition = (trackNum <= numPrimes);

    Parallel.ForEach(IterateUntilFalse(condition), (ignored, state) =>
    {
        if (trackNum > numPrimes) state.Stop();
        r.GetNonZeroBytes(makeBytes);
        makePrime = BigInteger.Abs(new BigInteger(makeBytes));
        if (CheckForPrime(makePrime))
        {
            bbag.Add(makePrime);
            if(bbag.TryPeek(out makePrime))
            {
                Console.WriteLine(makePrime);
            }
            Interlocked.Increment(ref trackNum);
        }
    });
}

I want to generate large prime numbers using the performance of Parallel.ForEach, and then print them out as it finds them.我想使用 Parallel.ForEach 的性能生成大素数,然后在找到它们时将它们打印出来。 The problem seems like the code is "bypassing" the if statement in the loop and adding non-prime numbers to the concurrent bag too.问题似乎是代码“绕过”了循环中的 if 语句,并将非素数添加到并发包中。 Is there a way to avoid this and guarantee that only the prime numbers be added to the bag and then printed sequentially?有没有办法避免这种情况并保证只将素数添加到袋子中然后按顺序打印?

bool condition is not a condition, it's the result of evaluating the condition once. bool condition不是条件,它是对条件进行一次评估的结果。 Basically it is always true and will never change.基本上它总是true ,永远不会改变。 Therefore, your iterator will yield true forever.因此,您的迭代器将永远产生true

To solve that, you need a real condition that can be evaluated several times, like a Lambda expression.为了解决这个问题,您需要一个可以多次评估的真实条件,例如 Lambda 表达式。 But even with a lambda this won't work well due to race conditions in your local variables.但即使使用 lambda,由于局部变量中的竞争条件,这也不能很好地工作。

Actually I don't really see why you use Parallel.Foreach at all.实际上,我根本不明白您为什么要使用Parallel.Foreach If you want 500 primes, then use Parallel.For , not Parallel.Foreach .如果您想要 500 个素数,请使用Parallel.For ,而不是Parallel.Foreach

Instead of generating a huge amount of random numbers and checking them for primality, choose a random number and increment it until you find a prime number.与其生成大量随机数并检查它们的素数,不如选择一个随机数并增加它,直到找到一个素数。 That way it's guaranteed that you get one prime number for every random number input.这样可以保证您为每个随机数输入获得一个素数。

Concept:概念:

Parallel.For(0, numPrimes, (i, state)=>
{
    byte[] makeBytes = new byte[512];
    r.GetNonZeroBytes(makeBytes);
    BigInteger makePrime = BigInteger.Abs(new BigInteger(makeBytes));
    while (!IsPrime(makePrime))
       makePrime += 1;       // at some point, it will become prime
    bbag.Add(makePrime);
});

You probably want to start with an odd number and increment by 2.您可能希望从一个奇数开始并以 2 为增量。

You definitely want one RNG per thread instead of accessing a single global RNG, except you have a thread-safe RNG.你肯定希望每个线程有一个 RNG,而不是访问一个全局 RNG,除非你有一个线程安全的 RNG。

You also want the byte[] to be part of the state, so that it does not get recreated per loop and messes with garbage collection.您还希望byte[]成为状态的一部分,这样它就不会在每个循环中重新创建并与垃圾收集相混淆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM