たとえば、配列float []
またはdouble []
. それらをすぐに追加する必要があります。どうやってするの?このためのライブラリはありますか?
5 に答える
1 つの方法は、配列の分割を決定し、N スレッドに配列の指定された部分を読み取らせて、個々の合計を見つけることです。その後、最終スレッドは、これらの個々の合計をすべて加算して、最終出力を得ることができます。
真に高性能なコーディングを行う必要はあまりありませんでしたが、リストを n 個のセグメント (コアごとに 1 個) に分割し、各コアが小計を出し、小計を合計します。値を乗算するように求められた場合、ワーカーが 0 に遭遇するとすぐに答えが得られます。
public class ArrayAdder {
public double getTotal(double[] array) {
Worker workers[] = new Worker[Runtime.getRuntime().availableProcessors()];
for (int i = 0; i < workers.length - 1;i++) {
workers[i] = new Worker(array,
i * array.length / workers.length,
(i + 1) * array.length / workers.length);
}
workers[workers.length - 1] = new Worker(array,
(workers.length - 1) * array.length / workers.length,array.length);
double total = 0;
for (int i = 0;i < workers.length;i++) {
try {
workers[i].join();
total += workers[i].getSum();
} catch (InterruptedException e) {
i--; //retry the wait for worker[i]
}
}
return total;
}
static class Worker extends Thread {
public Worker(double[] array, int start, int end) {
super();
this.array = array;
this.start = start;
this.end = end;
start();
}
private double[] array;
private int start;
private int end;
private double sum;
@Override
public void run() {
for (int i=start;i < end;i++) {
sum += array[i];
}
}
public double getSum() { return sum; }
}
}
BigDecimal
予想される値の大きさに応じて、小計と合計を として格納することができます。もちろん、正確な答えが必要でない限り、それらを ints/longs として追加する方がはるかに高速です。明らかに、単にキャストしたりキャストしたりするだけでなく (より高速な場合があります)、丸めたいと考え、答えが~array.length / 2
半分の時間で、キャストはそれを間違った方向に「丸め」ます。
別の最適化として考えられるのは、ループを部分的に展開して、CPU のスーパースカラー機能を使用することです。
たとえば、パイプライン サイズが 4 int のアーキテクチャ (および JVM がインテリジェントな場合) では、次のように記述できます。
for(int i = 0; i < array.size(); i += 4)
{
c[i] = a[i] + b[i];
c[i+1] = a[i+1] + b[i+1];
c[i+2] = a[i+2] + b[i+2];
c[i+3] = a[i+3] + b[i+3];
}
ただし、異なるアーキテクチャ パイプライン サイズごとに異なるコードを記述する必要があります。