Javascript tensorflowjs抛出的WASM后端;未处理的拒绝(RuntimeError):索引超出范围;Reactjs中的错误

Javascript tensorflowjs抛出的WASM后端;未处理的拒绝(RuntimeError):索引超出范围;Reactjs中的错误,javascript,reactjs,webassembly,tensorflow.js,Javascript,Reactjs,Webassembly,Tensorflow.js,我正在尝试在react应用程序中为blazeface人脸检测模型设置WASM后端。尽管带vanillajs的演示可以在数小时内无任何错误地运行,但在react中,它会在打开cam超过3-5分钟后抛出“未处理拒绝(RuntimeError):索引越界错误” 整个应用程序因此错误而崩溃。从下面的错误日志来看,可能与disposeData()或disposedensor()函数有关,我猜它们与垃圾收集有关。但我不知道它是否是来自WASM库本身的bug。你知道为什么会这样吗 下面我还提供了渲染预测功能

我正在尝试在react应用程序中为blazeface人脸检测模型设置WASM后端。尽管带vanillajs的演示可以在数小时内无任何错误地运行,但在react中,它会在打开cam超过3-5分钟后抛出“未处理拒绝(RuntimeError):索引越界错误”

整个应用程序因此错误而崩溃。从下面的错误日志来看,可能与
disposeData()
disposedensor()
函数有关,我猜它们与垃圾收集有关。但我不知道它是否是来自WASM库本身的bug。你知道为什么会这样吗

下面我还提供了渲染预测功能

renderPrediction=async()=>{
const model=await blazeface.load({maxFaces:1,scoreThreshold:0.95});
如果(这个游戏){
const canvas=this.refCanvas.current;
const ctx=canvas.getContext(“2d”);
常量返回张量=假;
常量flipHorizontal=true;
const=true;
常数预测=等待模型.estimateFaces(
this.refVideo.current,
返回张量,
水平翻转,
注释框
);
如果(长度>0){
clearRect(0,0,canvas.width,canvas.height);
for(设i=0;i<0.length;i++){
if(返回张量){
预测[i].topLeft=预测[i].topLeft.arraySync();
预测[i].bottomRight=预测[i].bottomRight.arraySync();
如果(注释框){
预测[i]。landmarks=预测[i]。landmarks.arraySync();
}
}
试一试{
}捕捉(错误){
控制台日志(错误消息);
}
常数开始=预测[i]。左上角;
const end=预测[i]。右下角;
常量大小=[end[0]-start[0],end[1]-start[1]];
如果(注释框){
常数地标=预测[i]。地标;
ctx.fillStyle=“蓝色”;
for(设j=0;j
错误的完整日志:

Unhandled Rejection (RuntimeError): index out of bounds
(anonymous function)
unknown
./node_modules/@tensorflow/tfjs-backend-wasm/dist/tf-backend-wasm.esm.js/</tt</r</r._dispose_data
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/wasm-out/tfjs-backend-wasm.js:9



disposeData
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/backend_wasm.ts:115

  112 | 
  113 | disposeData(dataId: DataId) {
  114 |   const data = this.dataIdMap.get(dataId);
> 115 |   this.wasm._free(data.memoryOffset);
      | ^  116 |   this.wasm.tfjs.disposeData(data.id);
  117 |   this.dataIdMap.delete(dataId);
  118 | }

disposeTensor
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:838

  835 |     'tensors');
  836 | let res;
  837 | const inputMap = {};
> 838 | inputs.forEach((input, i) => {
      | ^  839 |     inputMap[i] = input;
  840 | });
  841 | return this.runKernelFunc((_, save) => {

dispose
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/tensor.ts:388
endScope
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:983
tidy/<
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:431

  428 | if (kernel != null) {
  429 |     kernelFunc = () => {
  430 |         const numDataIdsBefore = this.backend.numDataIds();
> 431 |         out = kernel.kernelFunc({ inputs, attrs, backend: this.backend });
      | ^  432 |         const outInfos = Array.isArray(out) ? out : [out];
  433 |         if (this.shouldCheckForMemLeaks()) {
  434 |             this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outInfos);

scopedRun
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:448

  445 | // inputsToSave and outputsToSave. Currently this is the set of ops
  446 | // with kernel support in the WASM backend. Once those ops and
  447 | // respective gradients are modularised we can remove this path.
> 448 | if (outputsToSave == null) {
      | ^  449 |     outputsToSave = [];
  450 | }
  451 | const outsToSave = outTensors.filter((_, i) => outputsToSave[i]);

tidy
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:431

  428 | if (kernel != null) {
  429 |     kernelFunc = () => {
  430 |         const numDataIdsBefore = this.backend.numDataIds();
> 431 |         out = kernel.kernelFunc({ inputs, attrs, backend: this.backend });
      | ^  432 |         const outInfos = Array.isArray(out) ? out : [out];
  433 |         if (this.shouldCheckForMemLeaks()) {
  434 |             this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outInfos);

tidy
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/globals.ts:190

  187 |     const tensors = getTensorsInContainer(container);
  188 |     tensors.forEach(tensor => tensor.dispose());
  189 | }
> 190 | /**
  191 |  * Keeps a `tf.Tensor` generated inside a `tf.tidy` from being disposed
  192 |  * automatically.
  193 |  */

estimateFaces
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/blazeface_reactjs/node_modules/@tensorflow-models/blazeface/dist/blazeface.esm.js:17
Camera/this.renderPrediction
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/blazeface_reactjs/src/Camera.js:148

  145 | const returnTensors = false;
  146 | const flipHorizontal = true;
  147 | const annotateBoxes = true;
> 148 | const predictions = await model.estimateFaces(
      | ^  149 |   this.refVideo.current,
  150 |   returnTensors,
  151 |   flipHorizontal,

async*Camera/this.renderPrediction
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/blazeface_reactjs/src/Camera.js:399

  396 |         // }
  397 |       }
  398 |     }
> 399 |     requestAnimationFrame(this.renderPrediction);
      | ^  400 |   }
  401 | };
  402 | 



未处理的拒绝(RuntimeError):索引超出范围
(匿名函数)
未知的
./node_modules/@tensorflow/tfjs backend-wasm/dist/tf-backend-wasm.esm.js/{
|^839 | inputMap[i]=输入;
840 | });
841 |返回此。runKernelFunc((|,save)=>{
处置
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/tensor.ts:388
内窥镜
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:983
整洁的/<
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:431
428 |如果(内核!=null){
429 | kernelFunc=()=>{
430 | const numDataIdsBefore=this.backend.numDataIds();
>431 | out=kernel.kernelFunc({inputs,attrs,backend:this.backend});
|^432 | const outingfos=Array.isArray(out)?out:[out];
433 |如果(此.shouldCheckForMemLeaks()){
434 |此项。检查kernelformleak(kernelName、numdataidsbree、outInfos);
scopedRun
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:448
445 |//inputsToSave和outputsToSave。目前这是操作集
446 |//在WASM后端支持内核。一旦这些操作和
447 |//各个梯度模块化,我们可以删除此路径。
>448 |如果(outputsToSave==null){
|^449 | outputsToSave=[];
450 | }
451 | const outsToSave=outTensors.filter(|,i)=>outputsToSave[i]);
整齐的
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/engine.ts:431
428 |如果(内核!=null){
429 | kernelFunc=()=>{
430 | const numDataIdsBefore=this.backend.numDataIds();
>431 | out=kernel.kernelFunc({inputs,attrs,backend:this.backend});
|^432 | const outingfos=Array.isArray(out)?out:[out];
433 |如果(此.shouldCheckForMemLeaks()){
434 |此项。检查kernelformleak(kernelName、numdataidsbree、outInfos);
整齐的
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/src/globals.ts:190
187 |常数张量=getTensorsInContainer(container);
188 | tensors.forEach(tensor=>tensor.dispose());
189 | }
> 190 | /**
191 |*防止在“tf.tidy”中生成的“tf.Tensor”被丢弃
192 |*自动。
193 |  */
估计面
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/blazeface_reactjs/node_modules/@tensorflow models/blazeface/dist/blazeface.esm.js:17
摄影机/此.renderPrediction
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/blazeface_reactjs/src/Camera.js:148
145 |常数返回张量=假;
146 | const flipHorizontal=真;
147 | const=true;
>148 |常数预测=等待模型。估计面(
|^149 | this.refVideo.current,
150 |返回张量,
151 |水平翻转,
异步*摄像机/this.renderPrediction
C:/Users/osman.cakir/Documents/osmancakirio/deepLearning/blazeface_reactjs/src/Camera.js:399
396 |         // }
397 |       }
398 |     }
>399 | requestAnimationFrame(此.renderPrediction);
| ^  400 |   }
401 | };
402 | 

使用张量进行预测后,您需要将张量从设备内存中释放出来,否则它会累积,并导致潜在的错误。这只需使用
tf.dispose()即可完成
手动指定要处理张量的位置。在对十位数进行预测后立即执行此操作
const predictions = await model.estimateFaces(
        this.refVideo.current,
        returnTensors,
        flipHorizontal,
        annotateBoxes
      );
          
tf.dispose(this.refVideo.current);          
tf.engine().startScope()
// handling image tensors function
tf.engine().endScope()