2016-11-05 12 views
2

私は入力ベクトルと行列の間にドット積を実行するために使用される小さなJavaメソッドを持っています。 ドットプロダクトメソッドをJavaでより速く効率的にするにはどうすればいいですか?

public void calcOutput() { 
    outputs = new float[output]; 
    float sum = 0F; 

    for(int j = 0; j < output; j++) { 
     for(int i = 0; i < input; i++) { 
      sum += inputs[i] * weights[j][i]; 
     } 

     outputs[j] = sum; 
    } 
} 

は、基本的にこれが行うことになっているもの「入力」私の入力ベクトルを取ると、私は「重み」と命名しているマトリックスと内積を実行している:ここではコードです。出力は出力ベクトル 'outputs'に配置されます。

これをもっと速くするか、より効率的にするにはどうすればよいですか?私の体重マトリックスは、それが助けるならば、マトリックスである必要はありません。私は対応するインデックスに簡単にアクセスする方法が必要です。

ありがとうございました

+0

このコードをベンチマークしましたか?なぜそれがより効率的になると思いますか? –

+0

@ cricket_007ええ、それは与えられた30-40ミリメートルの大きな入力と出力番号と大きなウェイトマトリックスを実行します。 – Seephor

+0

'inputs'ベクトルへのアクセス回数を減らすために、外側と内側のループを逆にすることで、分数的に高速化することができます。私は時間があれば、後で答えを書きます。 –

答えて

3

いいえ、何も良いことはありません。これは実装が可能な最も簡単な方法であり、アルゴリズムは良好なメモリキャッシングアプローチに従います。つまり、外側ループが配列の外側インデックスに続き、内側ループが1つのサブアレイ内の要素にループします。

おそらく、内部配列に一時変数を使用するのに役立つかもしれませんが、JITがこれを処理すると思います。

また、間違いがあります。sum変数は、メソッドのスコープではなく、外側のループのスコープにある必要があります。外側ループの繰り返しごとにリセットする必要があります。

for(int j = 0; j < output; j++) { 
    // NOTE the line: 
    float sum = 0; 
    // and the reference to inner array: 
    byte[] row = weights[j]; 
    for(int i = 0; i < input; i++) { 
     sum += inputs[i] * row[i]; 
    } 

    outputs[j] = sum; 
} 
1

ここで私は何をしますか。外側ループと内側ループを逆にすることで、配列inputsのルックアップ数を減らすことができます。また、sum変数は必要ありません。outputs配列で直接追加することもできます。

float[] outputs = new float[output]; 

    for(int i = 0; i < input; i++) { 
     float inputsI = inputs[i]; 
     for(int j = 0; j < output; j++) { 
      outputs[j] += inputsI * weights[j][i]; 
     } 

    } 

これはほんの少し早いと予想します。ほぼすべての現実世界のアプリケーションで、このような小型で最適化された最適化について心配する価値はありません。

関連する問題