【问题标题】:How can I make this prime finder operate in parallel我怎样才能让这个prime finder并行运行
【发布时间】:2010-08-13 21:27:00
【问题描述】:

我知道素数发现已经得到很好的研究,并且有很多不同的实现。我的问题是,使用提供的方法(代码示例),我该如何分解工作?它将运行的机器有 4 个四核超线程处理器和 16GB 内存。我意识到可以进行一些改进,特别是在IsPrime 方法中。我也知道,一旦列表中的项目超过int.MaxValue,就会出现问题。我不关心任何这些改进。我唯一关心的是如何分解工作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Prime
{
    class Program
    {
        static List<ulong> primes = new List<ulong>() { 2 };

        static void Main(string[] args)
        {
            ulong reportValue = 10;
            for (ulong possible = 3; possible <= ulong.MaxValue; possible += 2)
            {
                if (possible > reportValue)
                {
                    Console.WriteLine(String.Format("\nThere are {0} primes less than {1}.", primes.Count, reportValue));

                    try
                    {
                        checked
                        {
                            reportValue *= 10;
                        }
                    }
                    catch (OverflowException)
                    {
                        reportValue = ulong.MaxValue;
                    }
                }

                if (IsPrime(possible))
                {
                    primes.Add(possible);
                    Console.Write("\r" + possible);
                }
            }

            Console.WriteLine(primes[primes.Count - 1]);
            Console.ReadLine();
        }

        static bool IsPrime(ulong value)
        {
            foreach (ulong prime in primes)
            {
                if (value % prime == 0) return false;
                if (prime * prime > value) break;
            }

            return true;
        }
    }
}

我看到了 2 种基本方案:1)使用所有线程来测试单个数字,这可能对更高的素数非常有用,但我真的想不出如何实现它,或者 2)使用每个线程来测试单个可能的素数,当下一个要测试的数字大于找到的最高素数的平方时,这可能会导致找到不连续的素数串并遇到未使用的资源问题。

对我来说,这两种情况都只是在构建素数列表的早期阶段才具有挑战性,但我并不完全确定。这样做是为了个人练习打破这种工作。

【问题讨论】:

    标签: multithreading parallel-processing primes


    【解决方案1】:

    如果您愿意,您可以并行化这两种操作:检查一个素数和一次检查多个素数。虽然我不确定这会有所帮助。老实说,我会考虑删除 main() 中的线程。

    我试图忠实于您的算法,但为了加快速度,我使用了 x*x 而不是 reportvalue;如果您愿意,这是您可以轻松恢复的东西。

    为了进一步改进我的核心拆分,您可以确定一种算法,以根据数字的大小计算出执行除法所需的计算次数,并以这种方式拆分列表。 (也就是较小的数字需要更少的时间来划分,所以使第一个分区更大)

    另外,我对线程池的概念可能不存在我想要使用它的方式

    这是我的尝试(伪代码):

    List<int> primes = {2};  
    List<int> nextPrimes = {};
    int cores = 4;
    main()
    {   
      for (int x = 3; x < MAX; x=x*x){  
        int localmax = x*x;
        for(int y = x; y < localmax; y+=2){  
          thread{primecheck(y);}
        }
      "wait for all threads to be executed"
      primes.add(nextPrimes);
      nextPrimes = {};
      }
    }
    
    void primecheck(int y)
    {  
      bool primality;  
      threadpool? pool;
      for(int x = 0; x < cores; x++){
        pool.add(thread{
          if (!smallcheck(x*primes.length/cores,(x+1)*primes.length/cores ,y)){
            primality = false;
            pool.kill();
          }
        });
      }  
      "wait for all threads to be executed or killed"
      if (primality)
        nextPrimes.add(y);  
    }
    
    bool smallcheck(int a, int b, int y){  
      foreach (int div in primes[a to b])  
        if (y%div == 0)  
          return false;  
      return true;
    }
    

    E:我添加了我认为池化应该是什么样子的,如果你不想看到它,请查看修订版。

    【讨论】:

      【解决方案2】:

      改用 Eratosthenes 的筛子。除非您首先使用好的算法,否则并行化是不值得的。

      分隔空间以筛选成大区域,并在各自的线程中筛选每个区域。或者更好地为大区域使用一些工作队列概念。

      使用位数组表示素数,比显式表示它们占用更少的空间。

      另请参阅this answer 以了解筛子的良好实现(在 Java 中,不分成区域)。

      【讨论】:

      • “除非你一开始就使用好的算法,否则并行化是不值得的。”该问题专门要求您并行化此实现,而不是另一个主要查找算法。该算法是否满足某种任意的价值衡量标准与如何并行化它无关。
      猜你喜欢
      • 1970-01-01
      • 2020-10-22
      • 2021-05-27
      • 2021-02-17
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-14
      相关资源
      最近更新 更多