javascript — Emscripten Uncaught RangeError: Источник слишком велик, несколько массивов Float32

Я пытаюсь запустить функцию C ++ для умножения матриц 4х4. Через 2 дня это наконец работает, но не так, как ожидалось.

Часто параметры передаются обратно в функцию, а затем в эту строку:

dataHeap2.set( new Uint8Array(data2.buffer) );

выдает ошибку «Uncaught RangeError: источник слишком велик»

На первый взгляд это выглядит как обычный Float32Array с 16 элементами, но после просмотра его размера буфера, похоже, он другой

console.log(data2.buffer.bufferLength);

В результате ожидается не 64 байта, а огромное число, например 3342345. В этом ли проблема? Я нашел обходной путь, вручную скопировав значения (как показано ниже), вернув их, и тогда проблема исчезла. К сожалению, это делает мой код намного медленнее, чем работа непосредственно на буферах.

// bad solution - which works
for(var i = 0; i < 16; i++) {
dataTarget[i] = result[i];
}

Надеюсь, этой ночью я найду лучшее решение и хочу продолжать использовать эту функцию, так как она использует скомпилированный код C ++ с использованием ASM.JS + SIMD для анимирования нескольких символов. В чистом JavaScript это все еще слишком медленно. Вот вся функция. Я почти уверен, что data2 использует HEAP от Emscripten, и я хочу избежать этого.

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);

5

Решение

Использовать голову 64 байта data2, укажите смещение и длину.

dataHeap2.set( new Uint8Array(data2.buffer, data2.byteOffset, nDataBytes) );
2

Другие решения

Кажется, это решает проблему, но я боюсь, что функция .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, потому что он замедляет все

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector