CANN运行时内存分配策略选择指南

发布时间:2026/7/11 15:51:44
CANN运行时内存分配策略选择指南 如何选择合适的内存分配策略【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime问题现象描述现象1内存分配性能不佳内存分配速度慢、访问性能低选择的页类型不适合业务场景。典型场景示例// 小块内存却配置了HUGE_ONLY策略实际占用远超需求 aclrtMalloc(devPtr, 1024, ACL_MEM_MALLOC_HUGE_ONLY); // 实际占用 2MB大页对齐现象2内存申请失败配置特定策略后内存申请失败如强制使用大页但大页内存不足。现象3P2P场景性能不佳跨Device复制场景使用普通策略而非P2P策略性能不佳。可能原因普通页 vs 大页选择不当不理解普通页和大页的性能特性、容量占用差异。P2P 场景未使用对应策略跨 Device 复制场景使用普通策略性能不佳。频繁申请释放内存未预分配复用导致性能损耗。处理步骤原因1普通页 vs 大页选择不当解决方法理解页类型特性普通页4K适合小块、短生命周期、数量多的内存申请减少对齐浪费2M大页适合大块、长期驻留、频繁访问的内存减少页表项、扩大TLB覆盖1G大页适合超大块、长期驻留、性能敏感的内存部分产品支持按数据大小选择策略≤1M使用 ACL_MEM_MALLOC_NORMAL_ONLY 或 HUGE_FIRST自动降级为普通页1M使用 ACL_MEM_MALLOC_HUGE_FIRST优先大页了解 HUGE_FIRST 机制申请大小 ≤1M 时即使配置 HUGE_FIRST 也使用普通页策略选择示例// 小块内存≤1M普通页或 HUGE_FIRST自动降级 size_t smallSize 1024 * 100; // 100KB aclrtMalloc(ptr1, smallSize, ACL_MEM_MALLOC_NORMAL_ONLY); // 普通页占用约100KB aclrtMalloc(ptr2, smallSize, ACL_MEM_MALLOC_HUGE_FIRST); // 自动使用普通页 // 大块内存1M大页优先 size_t largeSize 1024 * 1024 * 10; // 10MB aclrtMalloc(ptr3, largeSize, ACL_MEM_MALLOC_HUGE_FIRST); // 大页占用约10MB对齐到2M aclrtMalloc(ptr4, largeSize, ACL_MEM_MALLOC_HUGE_ONLY); // 仅大页不足时报错 // 强制大页场景对大页性能有强依赖 aclrtMalloc(ptr5, largeSize, ACL_MEM_MALLOC_HUGE_ONLY); // 大页不足时报错尽早暴露问题原因2P2P 场景未使用对应策略解决方法理解 P2P 场景跨 Device 数据复制内存需支持跨 Device 访问使用 P2P 策略选择带 P2P 后缀的策略HUGE_FIRST_P2P、HUGE_ONLY_P2P、NORMAL_ONLY_P2P使内存属性匹配访问路径P2P 策略确保内存属性与跨 Device 访问匹配P2P 策略示例// 跨 Device 复制场景 aclrtSetDevice(0); aclrtDeviceEnablePeerAccess(1, 0); // 开启 Device 0→1 的 P2P aclrtSetDevice(1); aclrtDeviceEnablePeerAccess(0, 0); // 开启 Device 1→0 的 P2P // Device 0 上申请用于 P2P 的内存 aclrtSetDevice(0); void* dev0Mem nullptr; aclrtMalloc(dev0Mem, size, ACL_MEM_MALLOC_HUGE_FIRST_P2P); // P2P 策略 // Device 1 上申请用于 P2P 的内存 aclrtSetDevice(1); void* dev1Mem nullptr; aclrtMalloc(dev1Mem, size, ACL_MEM_MALLOC_HUGE_FIRST_P2P); // P2P 策略 // 跨 Device 复制 aclrtMemcpy(dev1Mem, size, dev0Mem, size, ACL_MEMCPY_DEVICE_TO_DEVICE);原因3频繁申请释放内存解决方法预分配内存池初始化阶段预分配固定大小的内存业务侧复用避免频繁调用 aclrtMalloc/aclrtFree减少性能损耗预分配复用可显著提升性能内存池示例// 初始化阶段预分配内存池 #define POOL_SIZE 10 #define MEMORY_BLOCK_SIZE (1024 * 1024) // 1MB void* memoryPool[POOL_SIZE]; bool memoryPoolUsed[POOL_SIZE] {false}; void InitMemoryPool() { for (int i 0; i POOL_SIZE; i) { aclrtMalloc(memoryPool[i], MEMORY_BLOCK_SIZE, ACL_MEM_MALLOC_HUGE_FIRST); memoryPoolUsed[i] false; } } // 业务中申请内存从池中获取 void* AllocateFromPool() { for (int i 0; i POOL_SIZE; i) { if (!memoryPoolUsed[i]) { memoryPoolUsed[i] true; return memoryPool[i]; } } return nullptr; // 池已满 } // 业务中释放内存归还到池 void ReleaseToPool(void* ptr) { for (int i 0; i POOL_SIZE; i) { if (memoryPool[i] ptr) { memoryPoolUsed[i] false; return; } } } // 清理阶段释放池 void CleanupMemoryPool() { for (int i 0; i POOL_SIZE; i) { if (memoryPool[i] ! nullptr) { aclrtFree(memoryPool[i]); } } }相关 issueIssue #476: aclrtMallocPhysical申请大页内存限制【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考