使用 pexpect 的暗网多线程

问题描述 投票:0回答:1

我正在尝试使用 Darknet 和 Pexpact 并行处理 4 个图像。 当前的实现与此测试类似。检测一张图像需要 70ms,而并行检测 4 张图像需要 300ms。我是否做错了,或者我是否需要超过 1GPU 来进行此处理。

class Darknet: 
  def __init__(self): 
      self.instance = pexpect.spawn(f'darknet detector test {config.OBJ_DATA} {config.YOLOV3} {config.WEIGHTS} -ext_output -dont_show')
      self.instance.delaybeforesend = None
      self.instance.delayafterread = None
      self.instance.expect('Enter Image Path:')
      self.available = True

  def process(self, image_name): 
      self.instance.sendline(image_name)
      self.instance.expect('milli-seconds.', timeout=600)
      self.instance.expect('Enter Image Path:', timeout=600)
      output = self.instance.before
      logging.info(output)

      return output


class PexpectPerformanceTest(unittest.TestCase):
    def test_pexpect_speed(self):
        image_path = "/app/tmp/training_set/125_20231113_100730_609_3.jpg"
        darknet_instance_1 = SimpleDarknetThread(Darknet(), image_path)
        darknet_instance_2 = SimpleDarknetThread(Darknet(), image_path)
        darknet_instance_3 = SimpleDarknetThread(Darknet(), image_path)
        darknet_instance_4 = SimpleDarknetThread(Darknet(), image_path)

        darknet_instance_1.start()
        darknet_instance_2.start()
        darknet_instance_3.start()
        darknet_instance_4.start()

        darknet_instance_1.join()
        darknet_instance_2.join()
        darknet_instance_3.join()
        darknet_instance_4.join()

        print(f"Darknet 1 output: {darknet_instance_1.output}")
        print(f"Darknet 2 output: {darknet_instance_2.output}")
        print(f"Darknet 3 output: {darknet_instance_3.output}")
        print(f"Darknet 4 output: {darknet_instance_4.output}")


class SimpleDarknetThread(threading.Thread):
    def __init__(self, darknet, image_path):
        super().__init__()
        self.darknet = darknet
        self.image_path = image_path
        self.output = None

    def run(self):
        start_time = time.time()
        self.output = self.darknet.process(self.image_path)
        print(f"Required time: {(time.time() - start_time):.2f} s")


if __name__ == "main":
    unittest.main()
python multithreading spawn pexpect darknet
1个回答
0
投票

我对“pexpect”的了解为零。从您发布的代码来看,您似乎正在生成 Darknet 的多个 CLI 实例。

主要问题是运行时间最长的事情是将权重加载到 GPU 中。现在你已经将这次乘以 4!

另一个问题是加载权重会消耗大量的 vram,而 vram 的数量有限。根据您使用的配置以及您训练的维度,您可能没有足够的 vram 来一次加载神经网络的 4 个独立副本。

假设 vram 问题不是问题,让我向您展示为什么一次加载 4 个副本来处理每个副本恰好 1 个图像没有帮助。

当 Darknet 或 DarkHelp 运行时,它会输出加载神经网络所需的时间长度。就我而言,我将加载通常的 80 级 MSCOCO 网络,该网络在我拥有的 GPU 硬件上显示以下内容:

Done! Loaded 162 layers from weights-file 
-> loading network took 1335.175 milliseconds

处理图像需要额外花费 53.691 毫秒:

#1/1: loading "artwork/dog.jpg"
-> prediction took 53.691 milliseconds

因此,如果所有图像都具有相同的尺寸,则处理应该花费或多或少相同的时间。意思是每个 54 毫秒。加载该网络并处理 4 张图像的总时间为 1335 + 54 * 4 = 1551 毫秒。

现在,如果我在 4 次调用 Darknet 或 DarkHelp CLI 中执行此操作,我们会将加载时间乘以 4,得到 (1335 + 54) * 4 = 5556 毫秒。

很明显,加载 Darknet 或 DarkHelp 的多个副本,并在每个实例中处理 1 个图像并不是正确的解决方案。

相反,如果您使用 python,您应该做的是加载一次权重。然后,重复调用以处理所需数量的图像。 Darknet 和 DarkHelp 都有 python API。

给定 example.py 文件,API 应该足够容易使用。例如:

dh = DarkHelp.CreateDarkHelpNN(cfg_filename, names_filename, weights_filename)
DarkHelp.SetThreshold(dh, 0.35)
DarkHelp.SetAnnotationLineThickness(dh, 1)
DarkHelp.PredictFN(dh, "page_1.png".encode("utf-8"))
json = DarkHelp.GetPredictionResults(dh)

所以我们的想法是,只要有图像,您就可以多次调用

Predict()
PredictFN()
,然后调用
GetPredictionsResults()
。但在每种情况下,即使您正在处理数千张图像,您也只需加载一次权重。

现在,如果您想变得更有趣并且 GPU 上有足够的 vram,您可以实例化多个 Darknet 或 DarkHelp 对象。每个都加载重量。然后您可以并行使用每一个来同时处理多个图像。但您需要注意的是您的显存使用情况。运行

nvidia-smi
应该会告诉您每个实例正在使用多少 vram 以及您是否可以实例化另一个副本。

其他性能提示位于 YOLO 常见问题解答中:https://www.ccoderun.ca/programming/yolo_faq/#fps

复制到这里以防网址失效:

© www.soinside.com 2019 - 2024. All rights reserved.