【发布时间】: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