Array comparison for network evaluations

JavaScript performance comparison

Test case created by sutekidayo

Preparation code

<script>
var inputs = 40;
var hidden = 50;
var outputs = 10;

var inputValues = new Array(inputs);
for (var i = 0; i < inputs; i++){
    inputValues[i] = Math.random();
}

function Sigmoid(x) {
    return 1/(1+Math.exp(-x));
}

var numNeurons = hidden + outputs;
var numWeights = hidden*(inputs + outputs);

// Create 1D Float64Array Network
var Network1D = function(){
   this.Weights = new Float64Array(numWeights);
   for (var i=0; i < numWeights; i++){
       this.Weights[i] = Math.random();
   }
   this.Biases = new Float64Array(numNeurons);
   for (var i=0; i < numNeurons; i++){
    	this.Biases[i] = Math.random();
   }

   this.Outputs = new Float64Array(numNeurons + inputs);
   this.Layers = [inputs,hidden,outputs];
   this.outputLayer = this.Layers.length - 1;
   this.ComputeOutputs = function(input){
   		for (var i= 0,length = input.length;i<length;i++){
                    this.Outputs[i] = input[i];
        }
        // Compute the Outputs of each Layer
        var weights= 0, neurons = 0, outputs = this.Layers[0], output = 0;
        for (var layer = 1; layer <= this.outputLayer; layer++) {
            for (var neuron = 0, size = this.Layers[layer]; neuron < size; neuron++) {
                var sum = this.Biases[neurons];
                for (var z = 0, length = this.Layers[layer -1]; z < length; z++) {
                    sum += this.Weights[weights++] * this.Outputs[output+z];
                }
                this.Outputs[outputs++] = Sigmoid(sum);
            }
            output += length;
        }

        return Array.prototype.slice.call(this.Outputs,-this.Layers[this.outputLayer]);
   }
};

// Create 1D Float64Array Network with 3D Array Views
var Network1DViews = function(){
    this.Layers = [inputs,hidden,outputs];
    this.outputLayer = this.Layers.length - 1;


    this.randWeights = function (start, size) {
        var weights = this.WeightsBuffer.subarray(start,start + size);
        for (var i = 0; i < size; i++) {
            weights[i] = Math.random();
        }
        return weights;
    },

    this.randBias = function (offset,size) {
        var biases = this.BiasesBuffer.subarray(offset,offset+size);
        for (var i = 0; i < size; i++) {
            biases[i] = Math.random();;
        }
        return biases;
    };

    // Create Buffers
    this.WeightsBuffer = new Float64Array(numWeights);
    this.BiasesBuffer = new Float64Array(numNeurons);
    this.OutputsBuffer = new Float64Array(numNeurons + inputs);

    // Create Views
    this.Biases = [];
    this.Weights = [];
    this.Outputs = [];

    // Link Views to appropriate slices of the buffer;
    // Map first layer of Outputs to OutputsBuffer
    this.Outputs[0] = this.OutputsBuffer.subarray(0,this.Layers[0]);
    var offset = 0;
    var weight = 0;
    // Map the rest of the Array views to their Buffers
    for (var layer = 1; layer <= this.outputLayer; layer++) {
        var size = this.Layers[layer];
        this.Outputs[layer] = this.OutputsBuffer.subarray(offset+this.Layers[0],offset+this.Layers[0]+size);
        this.Biases[layer] = this.randBias(offset,size);
        this.Weights[layer] = new Array(size);
        for (var neuron = 0; neuron < size; neuron++) {
            var prevSize = this.Layers[layer - 1];
            this.Weights[layer][neuron] = this.randWeights(weight,prevSize);
            weight+=prevSize;
        }

        offset+=size;
    }

    this.ComputeOutputs = function(input){
        this.Outputs[0].set(input);
        // Compute the Outputs of each Layer
        for (var layer = 1; layer <= this.outputLayer; layer++) {
            for (var neuron = 0, size = this.Layers[layer]; neuron < size; neuron++) {
                var weights = this.Weights[layer][neuron];
                var sum = this.Biases[layer][neuron];
                for (var z = 0, length = weights.length; z < length; z++) {
                    sum += weights[z] * input[z];
                }
                this.Outputs[layer][neuron] = Sigmoid(sum);
            }
            var output = input = this.Outputs[layer];
        }

        return output;
    }
};

// Create 3D Network;
var Network3D = function(){
    this.Layers = [inputs,hidden,outputs];

    this.outputLayer = this.Layers.length - 1;
    this.randWeights = function (size) {
        var weights = new Array(size);
        for (var i = 0; i < size; i++) {
            weights[i] = Math.random();
        }
        return weights;
    };

    this.randBias = function (size) {
        var biases = new Array(size);
        for (var i = 0; i < size; i++) {
            biases[i] = Math.random();
        }
        return biases;
    };

    this.zeros = function (size) {
        var arr = new Array(size);
        for (var i = 0; i < size; i++) {
            arr[i] = 0;
        }
        return arr;
    };

    this.Biases = [];
    this.Weights = [];
    this.Outputs = [];

    for (var layer = 0; layer <= this.outputLayer; layer++) {
        var size = this.Layers[layer];
        this.Outputs[layer] = this.zeros(size);

        if (layer > 0) {
            this.Biases[layer] = this.randBias(size);
            this.Weights[layer] = new Array(size);

            for (var node = 0; node < size; node++) {
                var prevSize = this.Layers[layer - 1];
                this.Weights[layer][node] = this.randWeights(prevSize);

            }
        }
    }
    
    this.ComputeOutputs = function(input){
        this.Outputs[0] = input;
        // Compute the Outputs of each Layer
        for (var layer = 1; layer <= this.outputLayer; layer++) {
            for (var node = 0, nodes = this.Layers[layer]; node < nodes; node++) {
                var weights = this.Weights[layer][node];
                var sum = this.Biases[layer][node];
                for (var k = 0, length = weights.length; k < length; k++) {
                    sum += weights[k] * input[k];
                }
                this.Outputs[layer][node]=Sigmoid(sum);
            }
            var output = input = this.Outputs[layer];
        }

        return output;
    }
    
};

var NN1 = new Network1D();
var NN2 = new Network3D();
var NN3 = new Network1DViews();
</script>
    

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
1D Float64Array
NN1.ComputeOutputs(inputValues);
pending…
3D JavaScript Array
NN2.ComputeOutputs(inputValues);
pending…
3D Array of ArrayViews on Single Float64Array
NN3.ComputeOutputs(inputValues);
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL.

0 Comments