fix: ACL bytes_to_ptr GC bug + 添加 NPU 模型转换指南
python/infer_server.py: - 修复 acl.util.bytes_to_ptr() 后 bytes 被 GC 回收导致全零输出的 bug - 保持 bytes 引用直到 memcpy 完成 - 正确解析 FP16 模型输出 (half precision -> float32) docs/CONVERSION_GUIDE.md: - 完整的 YOLOv8 ONNX->OM 转换流程文档 - ATC 转换参数详解及低内存设备配置 - 已知问题排查表 (OOM/全零输出/算子不支持) - 其他 YOLOv8 尺寸模型参考 start.sh: 一键启动脚本
This commit is contained in:
@@ -112,10 +112,15 @@ class AclModel:
|
||||
def run(self, blob):
|
||||
"""Push blob to NPU, execute, pull outputs back as numpy arrays."""
|
||||
in_ds = acl.mdl.create_dataset()
|
||||
# Host input buffer - MUST keep reference alive during memcpy
|
||||
host_buf = np.ascontiguousarray(blob)
|
||||
host_bytes = host_buf.tobytes()
|
||||
host_addr = acl.util.bytes_to_ptr(host_bytes)
|
||||
# Device input buffer
|
||||
in_buf, ret = acl.rt.malloc(self.input_size, ACL_MEM_MALLOC_NORMAL_ONLY)
|
||||
assert ret == 0
|
||||
ret = acl.rt.memcpy(in_buf, self.input_size,
|
||||
blob.tobytes(), self.input_size,
|
||||
host_addr, self.input_size,
|
||||
ACL_MEMCPY_HOST_TO_DEVICE)
|
||||
assert ret == 0
|
||||
db = acl.create_data_buffer(in_buf, self.input_size)
|
||||
@@ -135,11 +140,27 @@ class AclModel:
|
||||
for i in range(self.output_num):
|
||||
sz = self.out_sizes[i]
|
||||
host = np.zeros(sz, dtype=np.uint8)
|
||||
ret = acl.rt.memcpy(host.ctypes.data, sz,
|
||||
# Keep reference alive during memcpy
|
||||
host_bytes = host.tobytes()
|
||||
host_addr = acl.util.bytes_to_ptr(host_bytes)
|
||||
ret = acl.rt.memcpy(host_addr, sz,
|
||||
self.out_bufs[i], sz,
|
||||
ACL_MEMCPY_DEVICE_TO_HOST)
|
||||
assert ret == 0
|
||||
outputs.append(host.view(np.float32).reshape(self.output_shapes[i]))
|
||||
# Read back from host_bytes (memcpy modified it)
|
||||
host_from_bytes = np.frombuffer(host_bytes, dtype=np.uint8)
|
||||
# FP16 model outputs are half precision (2 bytes)
|
||||
num_fp16 = sz // 2
|
||||
num_fp32 = sz // 4
|
||||
expected = self.output_shapes[i][0] * self.output_shapes[i][1] * self.output_shapes[i][2]
|
||||
if num_fp16 == expected:
|
||||
out_fp16 = host_from_bytes.view(np.float16)
|
||||
outputs.append(out_fp16.astype(np.float32).reshape(self.output_shapes[i]))
|
||||
elif num_fp32 == expected:
|
||||
outputs.append(host_from_bytes.view(np.float32).reshape(self.output_shapes[i]))
|
||||
else:
|
||||
out_fp16 = host_from_bytes.view(np.float16)
|
||||
outputs.append(out_fp16.astype(np.float32).reshape(self.output_shapes[i]))
|
||||
|
||||
acl.rt.free(in_buf)
|
||||
acl.mdl.destroy_dataset(in_ds)
|
||||
|
||||
Reference in New Issue
Block a user