// 跨设备复制,使用P2P直接访问,并增加健壮性检查
int32_t original_device_id = -1;
aclrtGetDevice(&original_device_id);
// --- 1. 检查并双向启用P2P访问 ---
int32_t can_access_peer = 0;
// 检查 src -> dst
ret = aclrtDeviceCanAccessPeer(&can_access_peer, src_gpu_id, dst_gpu_id);
if (ret != ACL_SUCCESS || can_access_peer == 0) {
fprintf(stderr, "[CAM %d] P2P access from src %d to dst %d is NOT supported (ret=%d, can_access=%d).\n", i, src_gpu_id, dst_gpu_id, ret, can_access_peer);
aclrtSetDevice(original_device_id);
return -1;
}
// 检查 dst -> src
ret = aclrtDeviceCanAccessPeer(&can_access_peer, dst_gpu_id, src_gpu_id);
if (ret != ACL_SUCCESS || can_access_peer == 0) {
fprintf(stderr, "[CAM %d] P2P access from dst %d to src %d is NOT supported (ret=%d, can_access=%d).\n", i, dst_gpu_id, src_gpu_id, ret, can_access_peer);
aclrtSetDevice(original_device_id);
return -1;
}
// 在源设备上使能对目标设备的访问
aclrtSetDevice(src_gpu_id);
ret = aclrtDeviceEnablePeerAccess(dst_gpu_id, 0);
if (ret != ACL_SUCCESS && ret != ACL_ERROR_REPEAT_INITIALIZE) {
fprintf(stderr, "[CAM %d] Enabling P2P from src %d to dst %d failed: %d\n", i, src_gpu_id, dst_gpu_id, ret);
aclrtSetDevice(original_device_id);
return ret;
}
// 在目标设备上使能对源设备的访问
aclrtSetDevice(dst_gpu_id);
ret = aclrtDeviceEnablePeerAccess(src_gpu_id, 0);
if (ret != ACL_SUCCESS && ret != ACL_ERROR_REPEAT_INITIALIZE) {
fprintf(stderr, "[CAM %d] Enabling P2P from dst %d to src %d failed: %d\n", i, dst_gpu_id, src_gpu_id, ret);
aclrtSetDevice(original_device_id);
return ret;
}
// --- 2. 在目标设备上分配临时中转内存 ---
y_size = camCtx->pool_stitch_scale_NV12_frm_array[frm_index]->linesize[0] * camCtx->pool_stitch_scale_NV12_frm_array[frm_index]->height;
uv_size = camCtx->pool_stitch_scale_NV12_frm_array[frm_index]->linesize[1] * camCtx->pool_stitch_scale_NV12_frm_array[frm_index]->height / 2;
size_t total_size = y_size + uv_size;
void* temp_device_buffer = nullptr;
aclrtSetDevice(dst_gpu_id); // 确保在目标设备上分配
ret = aclrtMalloc(&temp_device_buffer, total_size, ACL_MEM_MALLOC_HUGE_FIRST);
if (ret != ACL_SUCCESS) {
fprintf(stderr, "[CAM %d] Failed to allocate temporary device buffer on device %d, size %zu. ret=%d\n", i, dst_gpu_id, total_size, ret);
aclrtSetDevice(original_device_id);
return ret;
}
// --- 3. 从源设备上下文发起P2P复制,数据写入目标设备的临时内存 ---
aclrtSetDevice(src_gpu_id);
// Y平面
ret = aclrtMemcpy(temp_device_buffer, y_size, camCtx->pool_stitch_scale_NV12_frm_array[frm_index]->data[0], y_size, ACL_MEMCPY_DEVICE_TO_DEVICE);
if (ret != ACL_SUCCESS) {
fprintf(stderr, "[CAM %d] Failed P2P copy Y-plane from src %d to temp buffer on dst %d: %d\n", i, src_gpu_id, dst_gpu_id, ret);
aclrtSetDevice(dst_gpu_id);
aclrtFree(temp_device_buffer);
aclrtSetDevice(original_device_id);
return ret;
}
我双向检查了 aclrtDeviceCanAccessPeer 和 aclrtDeviceEnablePeerAccess , 然后aclrtSetDevice都成功,没有任何报错。
请帮忙看下,没有分析到具体的原因.
源码如下
备注:camCtx->pool_stitch_scale_NV12_frm_array 是分配在device上的ffmpeg AVFrame硬件帧
拷贝 y平面的时候就出错, 但是如果我从host往device侧memcpy就成功。跨卡的device_to_device就失败。
我双向检查了 aclrtDeviceCanAccessPeer 和 aclrtDeviceEnablePeerAccess , 然后aclrtSetDevice都成功,没有任何报错。
我看文档中写到 aclrtDeviceCanAccessPeer的约束,会不会是我的BIOS相关设置没有打开?
请帮忙看下,没有分析到具体的原因.
我的设备型号是6卡300V Pro, CANN8.0 ,npu-smi 24.1.0.1