title: Java: micro-optimizing array manipulation
body: <p>I am trying to make a Java port of a simple feed-forward neural network.<br>
  This obviously involves lots of numeric calculations, so I am trying to optimize my central loop as much as possible. The results should be correct within the limits of the <code>float</code> data type.</p>
  
  <p>My current code looks as follows (error handling &amp; initialization removed):</p>
  
  <pre><code>/**
   * Simple implementation of a feedforward neural network. The network supports
   * including a bias neuron with a constant output of 1.0 and weighted synapses
   * to hidden and output layers.
   * 
   * @author Martin Wiboe
   */
  public class FeedForwardNetwork {
  private final int outputNeurons;    // No of neurons in output layer
  private final int inputNeurons;     // No of neurons in input layer
  private int largestLayerNeurons;    // No of neurons in largest layer
  private final int numberLayers;     // No of layers
  private final int[] neuronCounts;   // Neuron count in each layer, 0 is input
                                  // layer.
  private final float[][][] fWeights; // Weights between neurons.
                                      // fWeight[fromLayer][fromNeuron][toNeuron]
                                      // is the weight from fromNeuron in
                                      // fromLayer to toNeuron in layer
                                      // fromLayer+1.
  private float[][] neuronOutput;     // Temporary storage of output from previous layer
  
  
  public float[] compute(float[] input) {
      // Copy input values to input layer output
      for (int i = 0; i &lt; inputNeurons; i++) {
          neuronOutput[0][i] = input[i];
      }
  
      // Loop through layers
      for (int layer = 1; layer &lt; numberLayers; layer++) {
  
          // Loop over neurons in the layer and determine weighted input sum
          for (int neuron = 0; neuron &lt; neuronCounts[layer]; neuron++) {
              // Bias neuron is the last neuron in the previous layer
              int biasNeuron = neuronCounts[layer - 1];
  
              // Get weighted input from bias neuron - output is always 1.0
              float activation = 1.0F * fWeights[layer - 1][biasNeuron][neuron];
  
              // Get weighted inputs from rest of neurons in previous layer
              for (int inputNeuron = 0; inputNeuron &lt; biasNeuron; inputNeuron++) {
                  activation += neuronOutput[layer-1][inputNeuron] * fWeights[layer - 1][inputNeuron][neuron];
              }
  
              // Store neuron output for next round of computation
              neuronOutput[layer][neuron] = sigmoid(activation);
          }
      }
  
      // Return output from network = output from last layer
      float[] result = new float[outputNeurons];
      for (int i = 0; i &lt; outputNeurons; i++)
          result[i] = neuronOutput[numberLayers - 1][i];
  
      return result;
  }
  
  private final static float sigmoid(final float input) {
      return (float) (1.0F / (1.0F + Math.exp(-1.0F * input)));
  }
  }
  </code></pre>
  
  <p>I am running the JVM with the -server option, and as of now my code is between 25% and 50% slower than similar C code. What can I do to improve this situation?</p>
  
  <p>Thank you,</p>
  
  <p>Martin Wiboe</p>
  
  <p>Edit #1: After seeing the vast amount of responses, I should probably clarify the numbers in our scenario. During a typical run, the method will be called about 50.000 times with different inputs. A typical network would have numberLayers = 3 layers with 190, 2 and 1 neuron, respectively. The innermost loop will therefore have about <code>2*191+3=385</code> iterations (when counting the added bias neuron in layers 0 and 1)</p>
  
  <p>Edit #1: After implementing the various suggestions in this thread, our implementation is practically as fast as the C version (within ~2 %). Thanks for all the help! All of the suggestions have been helpful, but since I can only mark one answer as the correct one, I will give it to @Durandal for both suggesting array optimizations and being the only one to precalculate the <code>for</code> loop header.</p>