You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何优化YOLOv8+SORT目标检测追踪代码以充分利用GPU算力?

如何优化YOLOv8+SORT目标检测追踪代码以充分利用GPU算力?

嘿,我来帮你排查并优化你的YOLOv8+SORT代码,让你的RTX4060Ti真正跑起来!GPU使用率低通常是因为大量计算在CPU上跑或者数据传输开销太大,咱们一步步来解决:

1. 先确认GPU环境真的生效

先在代码开头加几行验证,确保PyTorch确实在调用你的GPU:

print(f"CUDA可用: {torch.cuda.is_available()}")
print(f"当前GPU: {torch.cuda.get_device_name(0)}")
print(f"PyTorch CUDA版本: {torch.version.cuda}")

如果输出里看不到RTX4060Ti,那可能是环境没配好——比如重新安装和系统CUDA版本匹配的PyTorch,这是基础前提。

2. 把YOLOv8的推理和预处理全移到GPU

你现在的代码里,cap.read()得到的帧是CPU上的numpy数组,虽然YOLO会自动转GPU,但手动优化预处理流程能减少传输开销:

while True:
    ret, frame = cap.read()  
    if not ret:
        print("**No frame received**")
        continue

    # 直接把帧转成GPU张量,跳过CPU到GPU的隐式转换
    frame_tensor = torch.from_numpy(frame).to(device).permute(2, 0, 1).float() / 255.0
    # 添加batch维度(YOLOv8默认接受批量输入)
    frame_tensor = frame_tensor.unsqueeze(0)

    # 用半精度推理,大幅提升速度(RTX4060Ti完美支持FP16)
    results = model(frame_tensor, half=True, verbose=False)

model()直接推理比model.predict()更轻量,适合实时场景。

3. 改造SORT追踪器,让它在GPU上运行

这是核心!默认的SORT完全用numpy在CPU上计算,会吃掉大量CPU资源,同时让GPU闲下来。你需要修改src/sort.py里的代码,把所有计算移到GPU:

  • 把所有numpy数组换成torch.cuda.Tensor
  • 用PyTorch的torchvision.ops.box_iou代替SORT里的CPU版IOU计算
  • 把卡尔曼滤波的矩阵运算改成PyTorch的GPU张量运算

比如改造后的SORT update方法核心部分:

# 改造后直接接收GPU上的检测框张量
def update(self, dets=None):
    if dets is not None:
        # 用GPU加速的IOU计算
        iou_matrix = torchvision.ops.box_iou(self.tracks_boxes, dets[:, :4])
        # 剩下的匹配、卡尔曼更新都用GPU张量完成
        ...

这样SORT的核心计算就全在GPU上了,CPU负载会立刻降下来。

4. 用OpenCV的CUDA模块加速帧处理

你已经编译了带CUDA的OpenCV,一定要用上它的GPU加速函数!比如帧的resize、格式转换都用CUDA版本:

# 把CPU帧上传到GPU
gpu_frame = cv2.cuda_GpuMat()
gpu_frame.upload(frame)

# 用CUDA版resize代替CPU版
gpu_resized = cv2.cuda.resize(gpu_frame, (640, 640))

# 直接从GpuMat转成PyTorch张量,不用先下载回CPU
frame_tensor = torch.as_tensor(gpu_resized.download(), device=device).permute(2,0,1).float()/255.0

这一步能减少CPU在帧预处理上的开销。

5. 减少不必要的CPU-GPU数据传输

原来的代码里,你可能会把GPU上的检测结果转到CPU给SORT,再把追踪结果转回GPU——这来回传输非常耗时。改造SORT后,让检测框和追踪框全程留在GPU上,直到最后要画框显示的时候,再把结果转到CPU:

# 推理得到GPU上的检测框
detections = results[0].boxes.data  # 这是cuda张量
# 传给改造后的GPU版SORT
tracks = sort_tracker.update(detections)
# 最后要画框时,再转到CPU
tracks_cpu = tracks.cpu().numpy()
# 用OpenCV画框(这部分只能在CPU)
for track in tracks_cpu:
    x1, y1, x2, y2, track_id = track
    cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0,255,0), 2)

6. 其他小优化

  • 关闭YOLOv8的verbose输出:verbose=False,减少CPU的日志处理
  • 固定输入尺寸:比如imgsz=640,不要动态改变,让GPU保持稳定的计算负载
  • 关闭不必要的后处理:如果不需要分割掩码等结果,推理时指定task='detect'

备注:内容来源于stack exchange,提问作者S Andrew

火山引擎 最新活动