Java 高效并行素分解

Java 高效并行素分解,java,parallel-processing,primes,factorization,Java,Parallel Processing,Primes,Factorization,我正在尝试用Java制作一个并行版本的素因子分解,并且有一个工作程序。然而,这个程序非常慢——比我的顺序版本慢得多。我知道这可能与线程优化和线程数量有关(我尝试使用ExecutorService,但我认为我没有真正掌握其中的诀窍)。谁能指出优化这段代码的方法 class HovedFaktorArbeider implements Runnable //Class for first step factorization { int fra; int til; int

我正在尝试用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();}
      }
    }
  }
class HovedFaktorArbeider为第一步分解实现可运行//类
{
int fra;
int til;
int-id;
List tempFaktorer;//我们偶然发现大于int.MAX_值的素数,这肯定是很久以前的事了
长[]lokaleFaktorer;
CyclicBarrier faktorBarrier=新的CyclicBarrier(k+1);
ExecutorService ExecutorService=Executors.newFixedThreadPool(2);
长g;
公共住宅区(内部fra、内部til、内部id)
{
this.fra=fra;
this.til=til;
this.id=id;
}
公开募捐
{
尝试
{
//int tempK=2;//为aa sjekke设置裸k
长tempN=(长)n;
g=(tempN*tempN)-100;
long-tall=g+(long)fra;//要分解的长数
对于(inti=fra;i0)//如果不是完全除法
{
rest=(primes.size()%k);//保存余数
faktor=(primes.size()/k);//保存除数,扩展余数
rest--;//递减余数
}
else//If完全除法
faktor=primes.size()/k;
试探符=faktor;//设置结束值
tempFaktorer=newarraylist();
for(int ii=0;ii0)
{
试探符+=faktor+1;//展开余数
休息——;
}
其他的
试探符+=faktor;//新的结束值
}
faktorBarrier.wait();
lokaleFaktorer=新长[tempFaktorer.size()];
对于(int j=0;j1&&id==0&&!tempFaktorer.contains(t))
{
尝试
{
oppdaterTempFaktorer(t);
}
catch(异常e){e.printStackTrace();}
}
faktorBarrier.wait();
}
catch(异常e){e.printStackTrace();}
}
}
}
到目前为止,我有一个通过Erastothenes筛找到的素数列表,一个极限n和核k(在我的机器上是8)


注:之所以有两个可运行类,是因为我需要每个分解都由多个线程执行

如果您对并发感兴趣,我建议您看看其他并发模型,如
未来
参与者
。线程和锁很快就会在2007年出现

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

因此,从你的问题开始,使用并行体系结构并不是一个很好的问题,正如你所看到的,因为例如,假设你有9个线程,你检查数字2,3,4,5,6,7,8,9,10,这已经很糟糕了,因为你不必检查4,6,8,9,10,因为2&3会告诉你那些是很糟糕的(好的,你可能不会检查偶数,但只是为了证明我的观点)。所以有些问题不能很好地利用并行代码,正如你在这里看到的

至于你关于如何有效地并行Java代码的问题,最为人接受的答案是不要。现在程序员更关心的是不要阻塞线程,这些线程通常围绕着
不要叫我,我们会叫你
负责人。但是如何为数学问题编写有效的并行代码是一个过于复杂的问题广告计算机科学问题


但一般来说,您的问题太宽泛。

计算范围(与I/O范围相反)程序使用的线程数量应与您拥有的CPU数量大致相同。您使用
ExecutorService
的方法是正确的。google
为什么java中的多线程速度变慢了,您会有很多原因。抱歉,我不知道您的代码在做什么。也许您可以解释一下。您试图计算的整数在哪里?