---
title: Host锁页内存使用
description: "在CANN编程框架中，Host内存可以是Pageable内存，也可以是Page-Locked内存（也称锁页内存或Pinned内存）："
url: https://www.hiascend.com/document/detail/zh/canncommercial/latest/programug/acldevg/runtime_doc_dev_0006.html
sourcePath: /source/zh/canncommercial/900/programug/acldevg/runtime_doc_dev_0006.html
indexId: bede53519fa728c6a06a8b74dcf1c97b0e9573a8882f48e0199ca91d44e98c0f73
---
# Host锁页内存使用

在CANN编程框架中，Host内存可以是Pageable内存，也可以是Page-Locked内存（也称锁页内存或Pinned内存）：

- Pageable内存，由操作系统统一管理。开发者可使用malloc、mmap等传统接口申请内存，使用free、munmap等接口释放内存。当内存压力较大时，Pageable内存会被换出到后备存储提供的交换空间中。当Pageable内存中的数据被传输到Device时，数据首先会被复制到缓冲区，然后通过DMA（Direct Memory Access）通道传输到Device。
- Page-Locked内存，即锁页内存。开发者需要用Runtime提供的API进行锁页内存的申请和释放，例如aclrtMallocHost、aclrtFreeHost等接口。对于锁页内存，虚拟页与物理页的映射关系固定，在其生命周期内不会被换出至交换空间。当锁页内存中的数据被传输至Device时，直接通过DMA通道传输，无需经过缓冲区，传输性能更优。
  在Runtime中，使用锁页内存的好处如下
  ：
  - 设备可以直接通过DMA访问主机内存，无需经过缓冲区，可以提供更好的传输性能；
  - 数据搬运过程无需CPU参与，可以实现数据的异步传输；
  - 数据的异步传输，使传输过程和计算过程可以相互掩盖，减少传输+计算的整体时长。


锁页内存可直接通过aclrtMallocHost接口申请，示例代码如下。如果需要在申请时指定内存的其他配置，例如自定义模块ID、配置VA（virtual address）一致性等，也可以使用aclrtMallocHostWithCfg接口申请。
```
// 资源初始化
......
// 申请锁页内存
void *hostPtr = NULL;
aclrtMallocHost(&hostPtr, size);
// 申请Device内存
void *devicePtr = NULL;
aclrtMalloc(&devicePtr, size, ACL_MEM_MALLOC_NORMAL_ONLY);
// 内存初始化
......
// 异步H2D
aclrtMemcpyAsync(devicePtr, size, hostPtr, size, ACL_MEMCPY_HOST_TO_DEVICE, stream);
// 等待异步拷贝完成
aclrtSynchronizeStream(stream);
// 资源释放
if (devicePtr) (void)aclrtFree(devicePtr);
if (hostPtr) (void)aclrtFreeHost(hostPtr);
......
```


若使用malloc/mmap等内存管理接口申请Pageable内存，当前Runtime提供了aclrtHostRegisterV2接口，用于将Pageable内存转换为锁页内存，供Device访问。请注意，当OS内核版本为5.10或更低时，此方法会导致异常，此时应通过aclrtMallocHost接口申请锁页内存。
```
// 申请Pageable内存
void *hostPtr = malloc(size);
// 注册为锁页内存(ACL_HOST_REG_PINNED)，并映射到Device(ACL_HOST_REG_MAPPED)
aclrtHostRegisterV2(hostPtr, size, ACL_HOST_REG_PINNED|ACL_HOST_REG_MAPPED);
// 获取Device地址
void *devicePtr = NULL;
aclrtHostGetDevicePointer(hostPtr, &devicePtr, 0);
// 任务通过Device地址访问对应内存
// 资源释放
aclrtHostUnregister(hostPtr);
free(hostPtr);
```


若涉及Host内存的VA（virtual address）一致性：

- Host内存可以通过aclrtHostRegister接口注册到Device，根据Host指针映射得到Device指针，供Device使用；默认情况下，对于同一块Host内存，Host和Device看到的虚拟地址是不同的；
- 如果需要Host和Device的虚拟地址保持一致，可以使用aclrtMallocHostWithCfg接口申请锁页内存，并在aclrtMallocConfig参数中指定ACL_RT_MEM_ATTR_VA_FLAG属性，后续再注册获取到的Device虚拟地址即可与Host虚拟地址一致。
