SetInterval() 和异步函数? CPU 和 TF.js 一起工作太辛苦了

SetInterval() and async function? CPU working too hard with TF.js

我在Tensorflow.js写了一个网络摄像头分类的代码。通过结合许多教程的建议,它现在可以工作了。然而,在目前的阶段,作为 Tensorflow.js 的系统来说,它是非常昂贵的。预测循环 while (true)。 Google Chrome 助手(渲染器)在浏览器中使用此代码 运行 的 CPU 的 50-60%。

对我来说,如果能减轻一些 CPU 压力,每 0.5-1 秒进行一次预测计算就足够了。但是,作为初学者,我仍然对如何将 setInterval() 添加到我当前的代码(替换 while(true)循环感到困惑。我想知道是否有人能指出我正确的方向?或者如果有任何其他方法可以避免此代码的 CPU 压力。非常感谢!


async function app() {

  const model = await tf.loadGraphModel(MODEL_URL);
  console.log('Successfully loaded model');

  const labels = ["not_monster", "monster"];

  console.log(labels);


  const webcam = await tf.data.webcam(video);


  while (true) {


    tf.engine().startScope();
    const img = await webcam.capture();
    const smalImg = tf.image.resizeBilinear(img, [224, 224]);
    const resized = tf.cast(smalImg, 'float32');

    const t4d = tf.tensor4d(Array.from(resized.dataSync()),[1,224,224,3]);


    const result = await model.predict(t4d); 

    result.print(); 
    result.as1D().argMax().print(); 
    const labelIndex = result.as1D().argMax(); 
    const predictionLabel = result.as1D().argMax().dataSync()[0];

    
    const predict = await result.data();
    const value = predict[predictionLabel];



    document.getElementById("demo").innerHTML = `
       Numeric prediction is: ${labelIndex}\n
       The predicted label is: ${labels[predictionLabel]}\n
       Confidence is: ${value}\n
    `;

    if (labels[predictionLabel] == "monster"){ 
     var data = {
       speed: 100
     }
     socket.emit("monster", data);
    }

    else {
     socket.emit("not_monster"); 
    }

    img.dispose();
    result.dispose();
    smalImg.dispose();
    resized.dispose();
    t4d.dispose();
    tf.engine().endScope();
    await tf.nextFrame();

    
  } // closes loop

} // closes app

requestAnimationFrame(() => this.app());

因为 requestAnimationFrame 会 运行 'app' 重复不需要也循环 'app'

  while (true) { ... }

您已经有一个 setinterval 循环:

requestAnimationFrame(() => this.app());

这与以下完全一样:

setInterval(() => this.app(), 16.66666666667);

(好吧,几乎完全一样。很难得到 1/60 秒的精确毫秒值)。

所以基本上你的应用程序已经有一个巨大的 while 循环,形式为 requestAnimationFrame(),如果你愿意,你也可以像我上面那样用 setInterval() 替换它。

这导致 this.app() 每秒被调用 60 次。

因此,执行一秒后,您将在后台得到 60 个 while 循环 运行ning(感谢 await)。

执行 10 秒后,您将在后台得到 600 个 while 循环 运行ning(等待对 Tensorflow 的 600 次调用)。

一分钟后,您将等待 3600 个对 Tensorflow 的并行调用。

10 分钟后,将等待 36000 个对 Tensorflow 的并行调用。

难怪它占用了 60% CPU 的时间。随着时间的推移,情况会变得更糟。

在尝试用 setInterval() 替换 requestAnimationFrame() 之前,我建议您先 删除 while() 。您不必删除 while 循环内的代码,只需删除末尾的 while (true) {}

requestAnimationFrame() 将尝试每秒调用您的函数 60 次(基本上充当 while 循环)。如果您想每 0.5 秒 运行 您的函数,而不是将其替换为:

setInterval(() => this.app(), 500);

每 1 秒运行 你的函数:

setInterval(() => this.app(), 1000);