141 lines
4.1 KiB
JavaScript
141 lines
4.1 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Spiking Neural Network Performance Benchmark
|
|
*
|
|
* Tests performance across different network sizes and configurations.
|
|
*/
|
|
|
|
const {
|
|
createFeedforwardSNN,
|
|
rateEncoding,
|
|
SIMDOps,
|
|
native,
|
|
version
|
|
} = require('spiking-neural');
|
|
|
|
console.log(`\nSNN Performance Benchmark v${version}`);
|
|
console.log(`Native SIMD: ${native ? 'Enabled (10-50x faster)' : 'JavaScript fallback'}\n`);
|
|
console.log('='.repeat(60));
|
|
|
|
// Network scaling benchmark
|
|
console.log('\n--- NETWORK SCALING ---\n');
|
|
|
|
const sizes = [100, 500, 1000, 2000];
|
|
const iterations = 100;
|
|
|
|
console.log('Neurons | Time/Step | Spikes/Step | Steps/Sec');
|
|
console.log('-'.repeat(50));
|
|
|
|
for (const size of sizes) {
|
|
const snn = createFeedforwardSNN([size, Math.floor(size / 2), 10], {
|
|
dt: 1.0,
|
|
lateral_inhibition: true
|
|
});
|
|
|
|
const input = new Float32Array(size).fill(0.5);
|
|
|
|
// Warmup
|
|
for (let i = 0; i < 10; i++) {
|
|
snn.step(rateEncoding(input, snn.dt, 100));
|
|
}
|
|
|
|
// Benchmark
|
|
const start = performance.now();
|
|
let total_spikes = 0;
|
|
for (let i = 0; i < iterations; i++) {
|
|
total_spikes += snn.step(rateEncoding(input, snn.dt, 100));
|
|
}
|
|
const elapsed = performance.now() - start;
|
|
|
|
const time_per_step = elapsed / iterations;
|
|
const spikes_per_step = total_spikes / iterations;
|
|
const steps_per_sec = Math.round(1000 / time_per_step);
|
|
|
|
console.log(`${size.toString().padStart(7)} | ${time_per_step.toFixed(3).padStart(9)}ms | ${spikes_per_step.toFixed(1).padStart(11)} | ${steps_per_sec.toString().padStart(9)}`);
|
|
}
|
|
|
|
// SIMD vector operations
|
|
console.log('\n--- SIMD VECTOR OPERATIONS ---\n');
|
|
|
|
const dimensions = [64, 128, 256, 512];
|
|
const vecIterations = 10000;
|
|
|
|
console.log('Dimension | Naive (ms) | SIMD (ms) | Speedup');
|
|
console.log('-'.repeat(50));
|
|
|
|
for (const dim of dimensions) {
|
|
const a = new Float32Array(dim).map(() => Math.random());
|
|
const b = new Float32Array(dim).map(() => Math.random());
|
|
|
|
// Naive dot product
|
|
let start = performance.now();
|
|
for (let i = 0; i < vecIterations; i++) {
|
|
let sum = 0;
|
|
for (let j = 0; j < dim; j++) sum += a[j] * b[j];
|
|
}
|
|
const naiveTime = performance.now() - start;
|
|
|
|
// SIMD dot product
|
|
start = performance.now();
|
|
for (let i = 0; i < vecIterations; i++) {
|
|
SIMDOps.dotProduct(a, b);
|
|
}
|
|
const simdTime = performance.now() - start;
|
|
|
|
const speedup = naiveTime / simdTime;
|
|
console.log(`${dim.toString().padStart(9)} | ${naiveTime.toFixed(2).padStart(10)} | ${simdTime.toFixed(2).padStart(9)} | ${speedup.toFixed(2)}x`);
|
|
}
|
|
|
|
// Distance benchmark
|
|
console.log('\n--- EUCLIDEAN DISTANCE ---\n');
|
|
|
|
console.log('Dimension | Naive (ms) | SIMD (ms) | Speedup');
|
|
console.log('-'.repeat(50));
|
|
|
|
for (const dim of dimensions) {
|
|
const a = new Float32Array(dim).map(() => Math.random());
|
|
const b = new Float32Array(dim).map(() => Math.random());
|
|
|
|
// Naive
|
|
let start = performance.now();
|
|
for (let i = 0; i < vecIterations; i++) {
|
|
let sum = 0;
|
|
for (let j = 0; j < dim; j++) {
|
|
const d = a[j] - b[j];
|
|
sum += d * d;
|
|
}
|
|
Math.sqrt(sum);
|
|
}
|
|
const naiveTime = performance.now() - start;
|
|
|
|
// SIMD
|
|
start = performance.now();
|
|
for (let i = 0; i < vecIterations; i++) {
|
|
SIMDOps.distance(a, b);
|
|
}
|
|
const simdTime = performance.now() - start;
|
|
|
|
const speedup = naiveTime / simdTime;
|
|
console.log(`${dim.toString().padStart(9)} | ${naiveTime.toFixed(2).padStart(10)} | ${simdTime.toFixed(2).padStart(9)} | ${speedup.toFixed(2)}x`);
|
|
}
|
|
|
|
// Memory usage
|
|
console.log('\n--- MEMORY USAGE ---\n');
|
|
|
|
const memBefore = process.memoryUsage().heapUsed;
|
|
const largeSnn = createFeedforwardSNN([1000, 500, 100], {});
|
|
const memAfter = process.memoryUsage().heapUsed;
|
|
const memUsed = (memAfter - memBefore) / 1024 / 1024;
|
|
|
|
console.log(`1000-500-100 network: ${memUsed.toFixed(2)} MB`);
|
|
console.log(`Per neuron: ${(memUsed * 1024 / 1600).toFixed(2)} KB`);
|
|
|
|
console.log('\n--- SUMMARY ---\n');
|
|
console.log('Key findings:');
|
|
console.log(' - Larger networks have better amortized overhead');
|
|
console.log(' - SIMD provides 1.2-2x speedup for vector ops');
|
|
console.log(` - Native addon: ${native ? '10-50x faster (enabled)' : 'not built (run npm run build:native)'}`);
|
|
|
|
console.log('\nBenchmark complete!\n');
|