Emscripten Uncaught RangeError: Source is too large, multipl
Emscripten Uncaught RangeError: Source is too large, multiple Float32Arrays
我试图为4x4矩阵乘法运行c++函数。2天后,它终于起作用了,但并不像预期的那样。
参数通常被反馈给函数,然后这一行:
dataHeap2.set( new Uint8Array(data2.buffer) );
产生错误"Uncaught RangeError: Source is too large"
乍一看,它看起来只是一个普通的Float32Array有16个元素,但在查看它的缓冲区大小后,它似乎是不同的
console.log(data2.buffer.bufferLength);
结果不是预期的64字节,而是像3342345这样的大数字。这就是问题所在吗?我通过手动复制值(如下所示)找到了一个解决方法,返回该值,然后问题就消失了。不幸的是,它使我的代码比直接在缓冲区上操作要慢得多。
// bad solution - which works
for(var i = 0; i < 16; i++) {
dataTarget[i] = result[i];
}
希望今晚我能找到一个更好的解决方案,我想继续使用这个函数,因为它是使用ASM.JS + SIMD来动画多个字符的编译c++代码。在纯JavaScript中,它仍然太慢了。这是整个函数。我很确定data2正在使用Emscripten的HEAP,我想避免它。
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;
}
编辑:简化版不用担心malloc等
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 uncommented) there's just white screen(but it looks like the game is working.
//return new Float32Array(Module.HEAPU8.buffer, this.dataPtr + 144, 16);
如果要使用data2
的头64字节,请指定偏移量和长度。
dataHeap2.set( new Uint8Array(data2.buffer, data2.byteOffset, nDataBytes) );
这似乎解决了问题,但我担心。set函数只复制数据,这不是一个真正的解决方案。至少比循环克隆更优雅一点(但它比"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));
};
我也讨厌创建新的Float32Array实例因为它减慢了所有
相关文章:
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 如何修复"too few arguments to function"?
- fopen 在创建大量文件后因 EFBIG "File too large" 而失败
- VC++ wcscpy_s随机断言"Buffer is too small"
- 从 std::ostream 重载 << 运算符时,为什么编译器会给出"too many parameters for this operator function"错误?
- Golang CGO with large char pointer语言 - SEGSERV
- Large digit numbers
- MPI_Scatterv/ Gatherv 使用带有"large" 2D 矩阵的C++会引发 MPI 错误
- VS说"Too few arguments...",但其他编译器给了我正确的输出?
- 连接到MySQL时如何修复xdev C++ api中的'string too long'错误
- (3^n + 2^n) % 10 for large n
- c++ (XORString): "recursive type or function dependency context too complex"
- 尝试在 eclipse CDT 中提取函数时"Too many declarations in selection"错误消息
- 将嵌套结构变量从 C++ 传递到C++ dll 会导致 (L "Buffer is too small" && 0)
- 将CFileDialog的默认视图设置为Large Icon
- GCC 抑制警告"too small to hold all values of"
- 模板专用化站点报告"too few template-parameter-lists"错误
- 如何在Windows Server 2012上工作时出现"OverflowError: Python int too large to convert to C long"错误进行转换?
- Emscripten Uncaught RangeError: Source is too large, multipl