admin管理员组文章数量:1415645
I'm trying to run a C++ function for 4x4 matrices multiplying. After 2 days it finally works, but not as expected.
Often parameters are being fed back to the function and then this line:
dataHeap2.set( new Uint8Array(data2.buffer) );
produces an error "Uncaught RangeError: Source is too large"
At a glance it looks like it's just a normal Float32Array with 16 elements, but after looking inside it's buffer size it seems to be different
console.log(data2.buffer.bufferLength);
The result are not expected 64 bytes but huge numbers like 3342345. Is this the problem? I found a workaround by manually copying values(like below), returning that and then the problem disappears. Unfortunately it makes my code much slower than operating directly on buffers.
// bad solution - which works
for(var i = 0; i < 16; i++) {
dataTarget[i] = result[i];
}
Hopefully this night I'll find a better solution and I want to keep using this function as it's using a piled C++ code using ASM.JS + SIMD for aninmating multiple characters. In pure JavaScript it's still too slow. Here's the entire function. I'm pretty sure that data2 is taking Emscripten's HEAP with it and I want to aviod it.
matrix4multiply = function(data, data2) {
// Import function from Emscripten generated file
var mmul_vec4 = Module.cwrap(
'mmul_vec4', 'number', ['number', 'number', 'number']
);
var dataTarget = new Float32Array(16);
// Get data byte size, allocate memory on Emscripten heap, and get pointer
var nDataBytes = dataTarget.length * dataTarget.BYTES_PER_ELEMENT;
// First matrix copy data to Emscripten heap
var dataPtr = Module._malloc(nDataBytes);
var dataPtr2 = Module._malloc(nDataBytes);
var dataPtr3 = Module._malloc(nDataBytes);
var dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, nDataBytes);
dataHeap.set( new Uint8Array(data.buffer) );
// second matrix allocate and copy to emscripten's heap
var dataHeap2 = new Uint8Array(Module.HEAPU8.buffer, dataPtr2, nDataBytes);
dataHeap2.set( new Uint8Array(data2.buffer) );
// target heap
var targetHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr3, nDataBytes);
targetHeap.set( new Uint8Array(dataTarget.buffer) );
// Call the function by passing a number pointing to the byte location of
// the array of pointers on the Emscripten heap. Emscripten knows what to do!
mmul_vec4(dataHeap.byteOffset, dataHeap2.byteOffset, targetHeap.byteOffset);
// get result
var result = new Float32Array(targetHeap.buffer, targetHeap.byteOffset, 16);
// bad solution - which works
//for(var i = 0; i < 16; i++) {
// dataTarget[i] = result[i];
//}
// Free memory
Module._free(dataHeap.byteOffset);
Module._free(dataHeap2.byteOffset);
Module._free(targetHeap.byteOffset);
return result;
}
Edit: simplified version don't worry about malloc etc
new Uint8Array(Module.HEAPU8.buffer, this.dataPtr, 64).set( new Uint8Array(data.buffer, data.byteOffset, 64) );
// second matrix allocate and copy to emscripten's heap
new Uint8Array(Module.HEAPU8.buffer, this.dataPtr + 72, 64).set( new Uint8Array(data2.buffer, data2.byteOffset, 64) );
// multiply first two parameters and return in the last one
this.mmul_vec4(this.dataPtr, this.dataPtr + 72, this.dataPtr + 144);
// like that it works, unfotunately copying is being made here
return new Float32Array(Module.HEAPU8.buffer.slice(this.dataPtr + 144, this.dataPtr + 208));
// with this version (if unmented) there's just white screen(but it looks like the game is working.
//return new Float32Array(Module.HEAPU8.buffer, this.dataPtr + 144, 16);
I'm trying to run a C++ function for 4x4 matrices multiplying. After 2 days it finally works, but not as expected.
Often parameters are being fed back to the function and then this line:
dataHeap2.set( new Uint8Array(data2.buffer) );
produces an error "Uncaught RangeError: Source is too large"
At a glance it looks like it's just a normal Float32Array with 16 elements, but after looking inside it's buffer size it seems to be different
console.log(data2.buffer.bufferLength);
The result are not expected 64 bytes but huge numbers like 3342345. Is this the problem? I found a workaround by manually copying values(like below), returning that and then the problem disappears. Unfortunately it makes my code much slower than operating directly on buffers.
// bad solution - which works
for(var i = 0; i < 16; i++) {
dataTarget[i] = result[i];
}
Hopefully this night I'll find a better solution and I want to keep using this function as it's using a piled C++ code using ASM.JS + SIMD for aninmating multiple characters. In pure JavaScript it's still too slow. Here's the entire function. I'm pretty sure that data2 is taking Emscripten's HEAP with it and I want to aviod it.
matrix4multiply = function(data, data2) {
// Import function from Emscripten generated file
var mmul_vec4 = Module.cwrap(
'mmul_vec4', 'number', ['number', 'number', 'number']
);
var dataTarget = new Float32Array(16);
// Get data byte size, allocate memory on Emscripten heap, and get pointer
var nDataBytes = dataTarget.length * dataTarget.BYTES_PER_ELEMENT;
// First matrix copy data to Emscripten heap
var dataPtr = Module._malloc(nDataBytes);
var dataPtr2 = Module._malloc(nDataBytes);
var dataPtr3 = Module._malloc(nDataBytes);
var dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, nDataBytes);
dataHeap.set( new Uint8Array(data.buffer) );
// second matrix allocate and copy to emscripten's heap
var dataHeap2 = new Uint8Array(Module.HEAPU8.buffer, dataPtr2, nDataBytes);
dataHeap2.set( new Uint8Array(data2.buffer) );
// target heap
var targetHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr3, nDataBytes);
targetHeap.set( new Uint8Array(dataTarget.buffer) );
// Call the function by passing a number pointing to the byte location of
// the array of pointers on the Emscripten heap. Emscripten knows what to do!
mmul_vec4(dataHeap.byteOffset, dataHeap2.byteOffset, targetHeap.byteOffset);
// get result
var result = new Float32Array(targetHeap.buffer, targetHeap.byteOffset, 16);
// bad solution - which works
//for(var i = 0; i < 16; i++) {
// dataTarget[i] = result[i];
//}
// Free memory
Module._free(dataHeap.byteOffset);
Module._free(dataHeap2.byteOffset);
Module._free(targetHeap.byteOffset);
return result;
}
Edit: simplified version don't worry about malloc etc
new Uint8Array(Module.HEAPU8.buffer, this.dataPtr, 64).set( new Uint8Array(data.buffer, data.byteOffset, 64) );
// second matrix allocate and copy to emscripten's heap
new Uint8Array(Module.HEAPU8.buffer, this.dataPtr + 72, 64).set( new Uint8Array(data2.buffer, data2.byteOffset, 64) );
// multiply first two parameters and return in the last one
this.mmul_vec4(this.dataPtr, this.dataPtr + 72, this.dataPtr + 144);
// like that it works, unfotunately copying is being made here
return new Float32Array(Module.HEAPU8.buffer.slice(this.dataPtr + 144, this.dataPtr + 208));
// with this version (if unmented) there's just white screen(but it looks like the game is working.
//return new Float32Array(Module.HEAPU8.buffer, this.dataPtr + 144, 16);
Share
Improve this question
edited Jul 22, 2015 at 6:07
Pawel
asked Jul 21, 2015 at 21:47
PawelPawel
18.3k6 gold badges78 silver badges76 bronze badges
3
- Asm.js seems to require single heap buffer. perhaps copying or malloc/free management required. asmjs/spec/latest/#validatemodule-f – zakki Commented Jul 22, 2015 at 6:42
- @zakki ok so I think copying to passed targetFloat32 will work, but I don't see how to feed this Module.HEAPU8.buffer, this.dataPtr + 144, 16 into existing Float32Array without creating a new instance like that: new Float32Array(Module.HEAPU8.buffer, this.dataPtr + 144, 16). That's too slow. – Pawel Commented Jul 22, 2015 at 13:27
- Had similar problem turned out to be buffer initialized to smaller value than the size of data being set. – vatsa Commented Aug 2, 2016 at 19:47
2 Answers
Reset to default 2To use head 64 bytes of data2
, specify offset and length.
dataHeap2.set( new Uint8Array(data2.buffer, data2.byteOffset, nDataBytes) );
This seems to solve the problem, but I'm afraid that .set function only copies data and it's not a real solution then. At least a bit more elegant than for loop cloning (but is it better than "Module.HEAPU8.buffer.slice")?
matrix4multiplyBlocking = function(data, data2, dataTarget) {
//console.log(new Float32Array(data2.buffer, data2.byteOffset, 16));
// Copy data to Emscripten heap
new Uint8Array(Module.HEAPU8.buffer, this.dataPtr, 64).set( new Uint8Array(data.buffer, data.byteOffset, 64) );
// second matrix allocate and copy to emscripten's heap
new Uint8Array(Module.HEAPU8.buffer, this.dataPtr + 72, 64).set( new Uint8Array(data2.buffer, data2.byteOffset, 64) );
// multiply first two parameters and return in the last one
this.mmul_vec4(this.dataPtr, this.dataPtr + 72, this.dataPtr + 144);
// Free memory
//Module._free(this.dataPtr);
dataTarget.set(new Float32Array(Module.HEAPU8.buffer, this.dataPtr + 144, 16));
};
Also I hate the fact of creating new Float32Array instance because it slows down everything
本文标签:
版权声明:本文标题:javascript - Emscripten Uncaught RangeError: Source is too large, multiple Float32Arrays - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745241832a2649373.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论