【问题标题】:Efficient parallel prime factorization高效的并行素数分解
【发布时间】:2018-05-01 04:18:51
【问题描述】:

我正在尝试用 Java 制作一个并行版本的素数分解,并有一个工作程序。但是,该程序非常慢——比我的顺序版本慢得多。我确实明白这可能与线程优化和线程的绝对数量有关(我尝试使用 ExecutorService 但我认为我并没有真正掌握它)。谁能指出优化这段代码的方法?

class HovedFaktorArbeider implements Runnable //Class for first step factorization
  {
    int fra;
    int til;
    int id;
    List<Long> tempFaktorer; //Must be long since we'll stumble upon primes larger than int.MAX_VALUE accidentally
    long[] lokaleFaktorer;
    CyclicBarrier faktorBarrier = new CyclicBarrier(k+1);
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    long g;

    public HovedFaktorArbeider(int fra, int til, int id)
    {
      this.fra = fra;
      this.til = til;
      this.id = id;
    }

    public void run()
    {
      try
      {
        //int tempK = 2; //Erstatter bare k for aa sjekke
        long tempN = (long) n;
        g = (tempN*tempN)-100;
        long tall = g + (long) fra; //The long numbers to be factorized
        for(int i = fra; i <= til; i++) //For the number split
        {
          int tempFra = 0;
          int tempTil = 0;
          int rest = 0;
          int faktor = 0;
          if(primes.size() % k > 0)  //If not perfect division
          {
            rest = (primes.size() % k);  //Saving remainder
            faktor = (primes.size()/k);  //Saving divisor, spreading remainder
            rest--; //Decrement remainder
          }
          else  //If perfect divison
            faktor = primes.size()/k;

          tempTil = faktor; //Setting end value

          tempFaktorer = new ArrayList<Long>();
          for(int ii = 0; ii < k; ii++) //For the prime number split
          {
            //executorService.submit(new HjelpeFaktorArbeider(tempFra, tempTil, tall, ii));
            new Thread(new HjelpeFaktorArbeider(tempFra, tempTil, tall, ii)).start();
            tempFra = tempTil + 1; //Set new value for start
            if(rest > 0)
            {
              tempTil += faktor + 1; //Spreading remainder
              rest--;
            }
            else
              tempTil += faktor; //New end value
          }
          faktorBarrier.await();
          lokaleFaktorer = new long[tempFaktorer.size()];
          for(int j = 0; j < tempFaktorer.size(); j++)
          {
            lokaleFaktorer[j] = tempFaktorer.get(j);
          }
          faktorer[i] = lokaleFaktorer; //TNB: i does not start at 0, so placement should be correct
          tall++;
        }
        mainBarrier.await();
        executorService.shutdown();
      }
      catch(Exception e){e.printStackTrace();}
    }

    public synchronized void oppdaterTempFaktorer(long tall)
    {
      tempFaktorer.add(tall);
    }

    class HjelpeFaktorArbeider implements Runnable //Class for second step factorization
    {
      int fra;
      int til;
      int id;
      long tall;


      public HjelpeFaktorArbeider(int fra, int til, long tall, int id)
      {
        this.fra = fra;
        this.til = til;
        this.id = id;
        this.tall = tall;
      }

      public void run()
      {
        try
        {
          long t = tall;
          for(int i = fra; i < til; i++)
          {
            int primtall = primes.get(i);

            while(t % primtall == 0)
            {
              try
              {
                oppdaterTempFaktorer((long) primtall);
              }
              catch(Exception e){e.printStackTrace();}

              t = t/primtall;
            }
          }
          runBarrier.await();
          if(t > 1 && id == 0 && !tempFaktorer.contains(t))
          {
            try
            {
              oppdaterTempFaktorer(t);
            }
            catch(Exception e){e.printStackTrace();}
          }
          faktorBarrier.await();
        }
        catch(Exception e){e.printStackTrace();}
      }
    }
  }

到目前为止,我有一个通过 Erastothenes 的筛子找到的素数列表、一个极限 n 和 k 个核(在我的机器上是 8 个)。

P.S.:之所以有两个 Runnable 类,是因为我需要每个分解都由多个线程执行。

【问题讨论】:

  • 计算密集型(与 I/O 密集型相反)程序使用的线程数应与 CPU 数量大致相同。您与ExecutorService 走在正确的轨道上。
  • google why it get slowed multithread in java,你会得到很多理由。
  • 对不起,我不知道你的代码在做什么。也许你可以解释一下。您要考虑的整数在哪里?

标签: java parallel-processing primes factorization


【解决方案1】:

如果您对并发感兴趣,我建议您查看其他并发模型,例如 FuturesActors。线程和锁是 SOooo0o 2007。

关于如何更好地使并行代码更快的问题,这是一个有很多方法的十亿美元问题。这完全取决于您的问题和架构。

因此,从您的问题开始,您可以看到使用并行架构并不是一个奇妙的问题,因为例如说您有 9 个线程,然后您检查数字 2、3、4、5、6、7 ,8,9,10,这已经很糟糕了,因为您不必检查 4,6,8,9,10,因为 2 和 3 会向您显示那些很糟糕(好吧,您可能不会检查偶数,但只是为了证明我的观点)。所以有些问题不能很好地利用并行代码,你可以在这里看到。

关于如何有效地并行化 Java 代码的问题,最广为接受的答案是不要。现在的程序员更关心不阻塞通常围绕don't call me we'll call you 主体的线程。但是如何为数学问题编写高效的并行代码是一个过于宽泛的计算机科学问题。

但总的来说,您的问题过于宽泛。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多