Skip to content

Instantly share code, notes, and snippets.

@jonathanlurie
Created March 10, 2017 22:01
Show Gist options
  • Save jonathanlurie/996487859988c6596a6f1e64e770ae79 to your computer and use it in GitHub Desktop.
Save jonathanlurie/996487859988c6596a6f1e64e770ae79 to your computer and use it in GitHub Desktop.
Emscripten and float arrays v3
#include <math.h>
// otherwise C++ function names are mangled
extern "C" {
void float_multiply_array(float *data, int w, int h, int ncpp) {
int length = w*h;
int currentPixelIndex = 0;
int currentPixelIndexUnderFilter = 0;
/*
float filter[3][3] = {
{1/9, 1/9, 1/9},
{1/9, 1/9, 1/9},
{1/9, 1/9, 1/9}
};
*/
float filter[9][9] = {
{0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067},
{0.00002292, 0.00078634, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},
{0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},
{0.00038771, 0.01330373, 0.11098164, 0.22508352, 0.11098164, 0.01330373, 0.00038771},
{0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},
{0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},
{0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067}
};
// one side size
int filterSize = 9;
int filterHalfSize = floor( filterSize / 2 );
int startX = filterHalfSize;
int startY = startX;
int endX = w - filterHalfSize;
int endY = h - filterHalfSize;
float tempColor = 0;
for(int i=startX; i<endX; i++){
for(int j=startY; j<endY; j++){
currentPixelIndex = j * w + i;
tempColor = 0;
// along filter width
for(int iFilter=0; iFilter<filterSize; iFilter++){
// along filter height
for(int jFilter=0; jFilter<filterSize; jFilter++){
int iUnderFilter = i + iFilter - filterHalfSize;
int jUnderFilter = j + jFilter - filterHalfSize;
currentPixelIndexUnderFilter = jUnderFilter * w + iUnderFilter;
tempColor += data[currentPixelIndexUnderFilter] * filter[iFilter][jFilter];
}
}
data[currentPixelIndex] = tempColor;
}
}
}
}
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Emscripten-Generated Code</title>
<script type="text/javascript" src="arrayFunction.js"></script>
</head>
<body>
<script>
function arrayFunctionCpp(w, h, ncpp){
var length = w * h * ncpp;
// Create example data to test float_multiply_array
var data = new Float32Array(length);
data[5] = 10;
var t0 = performance.now();
// Import function from Emscripten generated file
float_multiply_array = Module.cwrap(
'float_multiply_array', null, ['number', 'number', 'number']
);
// Get data byte size, allocate memory on Emscripten heap, and get pointer
var nDataBytes = data.length * data.BYTES_PER_ELEMENT;
//Module.TOTAL_MEMORY = nDataBytes; // added by jo
var dataPtr = Module._malloc(nDataBytes);
// Copy data to Emscripten heap (directly accessed from Module.HEAPU8)
var dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, nDataBytes);
dataHeap.set(new Uint8Array(data.buffer));
var t0bis = performance.now();
// Call function and get result
float_multiply_array(dataHeap.byteOffset, w, h, ncpp);
var t1bis = performance.now();
var result = new Float32Array(dataHeap.buffer, dataHeap.byteOffset, data.length);
// Free memory
Module._free(dataHeap.byteOffset);
var t1 = performance.now();
console.log("C++ took " + (t1 - t0) + " milliseconds. (including memory transfer)");
console.log("C++ took " + (t1bis - t0bis) + " milliseconds. (just function runtime)");
console.log( result );
}
function arrayFunctionJs(w, h, ncpp){
var length = w * h * ncpp;
// Create example data to test float_multiply_array
var data = new Float32Array( length );
data[5] = 10;
var t0 = performance.now();
var currentPixelIndex = 0;
var currentPixelIndexUnderFilter = 0;
/*
var filter = [
[1/9, 1/9, 1/9],
[1/9, 1/9, 1/9],
[1/9, 1/9, 1/9]
];
*/
var filter = [
[0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067],
[0.00002292, 0.00078634, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292],
[0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117],
[0.00038771, 0.01330373, 0.11098164, 0.22508352, 0.11098164, 0.01330373, 0.00038771],
[0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117],
[0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292],
[0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067]
];
// one side size
var filterSize = filter.length;
var filterHalfSize = Math.floor( filterSize / 2 );
var startX = filterHalfSize;
var startY = startX;
var endX = w - filterHalfSize;
var endY = h - filterHalfSize;
var tempColor = 0;
for(var i=startX; i<endX; i++){
for(var j=startY; j<endY; j++){
currentPixelIndex = j * w + i;
tempColor = 0;
// along filter width
for(var iFilter=0; iFilter<filterSize; iFilter++){
// along filter height
for(var jFilter=0; jFilter<filterSize; jFilter++){
var iUnderFilter = i + iFilter - filterHalfSize;
var jUnderFilter = j + jFilter - filterHalfSize;
currentPixelIndexUnderFilter = jUnderFilter * w + iUnderFilter;
tempColor += data[currentPixelIndexUnderFilter]*filter[iFilter][jFilter];
}
}
data[currentPixelIndex] = tempColor;
}
}
var t1 = performance.now();
console.log("JS took " + (t1 - t0) + " milliseconds.");
console.log(data);
}
var w = 10000;
var h = 10000;
var ncpp = 1;
arrayFunctionCpp( w, h, ncpp );
arrayFunctionJs( w, h, ncpp );
//------------------------------
</script>
</body>
</html>
//============================================================================
// Name : test0.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <math.h>
using namespace std;
void float_multiply_array(float *data, int w, int h, int ncpp);
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
int w = 10000;
int h = 10000;
int ncpp = 1;
float * data = new float[h*w];
float_multiply_array(data, w, h, ncpp);
delete[] data;
return 0;
}
void float_multiply_array(float *data, int w, int h, int ncpp) {
int currentPixelIndex = 0;
int currentPixelIndexUnderFilter = 0;
float filter[9][9] = {
{0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067},
{0.00002292, 0.00078634, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},
{0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},
{0.00038771, 0.01330373, 0.11098164, 0.22508352, 0.11098164, 0.01330373, 0.00038771},
{0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},
{0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},
{0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067}
};
// one side size
int filterSize = 9;
int filterHalfSize = floor( filterSize / 2 );
int startX = filterHalfSize;
int startY = startX;
int endX = w - filterHalfSize;
int endY = h - filterHalfSize;
float tempColor = 0;
for(int i=startX; i<endX; i++){
for(int j=startY; j<endY; j++){
currentPixelIndex = j * w + i;
tempColor = 0;
// along filter width
for(int iFilter=0; iFilter<filterSize; iFilter++){
// along filter height
for(int jFilter=0; jFilter<filterSize; jFilter++){
int iUnderFilter = i + iFilter - filterHalfSize;
int jUnderFilter = j + jFilter - filterHalfSize;
currentPixelIndexUnderFilter = jUnderFilter * w + iUnderFilter;
tempColor += data[currentPixelIndexUnderFilter] * filter[iFilter][jFilter];
}
}
data[currentPixelIndex] = tempColor;
}
}
}
emcc -O3 arrayFunction.cpp -o arrayFunction.js -s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_FUNCTIONS="['_float_multiply_array']"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment