高级内存优化
note
本篇文档的数字仅做示例参考。具体数据,请以实际情况为准。
本文档帮你深入理解 MUSA 高级内存特性:系统内存优化、L2 缓存管理、Cluster 内存和异步执行。
页锁定内存
分配和释放
#include <musa.h>
#include <stdio.h>
int main() {
size_t size = 1000000 * sizeof(float);
// 分配页锁定内存
float* h_pinned;
musaMallocHost(&h_pinned, size);
// 初始化数据
for (int i = 0; i < 1000000; i++) {
h_pinned[i] = float(i);
}
// 使用完成后释放
musaFreeHost(h_pinned);
return 0;
}
异步内存传输
void asyncTransfer(float* h_pinned, float* d_data, size_t size) {
musaStream_t stream;
musaStreamCreate(&stream);
// 异步 H2D 拷贝
musaMemcpyAsync(d_data, h_pinned, size,
musaMemcpyHostToDevice, stream);
// 启动 kernel(与传输重叠)
processKernel<<<grid, block, 0, stream>>>(d_data);
// 异步 D2H 拷贝
musaMemcpyAsync(h_pinned, d_data, size,
musaMemcpyDeviceToHost, stream);
// 等待完成
musaStreamSynchronize(stream);
musaStreamDestroy(stream);
}
流水线传输
void pipelineTransfer(float* h_input, float* h_output, int n) {
float *d_input, *d_output;
musaMalloc(&d_input, n * sizeof(float));
musaMalloc(&d_output, n * sizeof(float));
// 分配 pinned buffers
float *h_pinned_in, *h_pinned_out;
musaMallocHost(&h_pinned_in, n * sizeof(float));
musaMallocHost(&h_pinned_out, n * sizeof(float));
musaStream_t stream;
musaStreamCreate(&stream);
// 拷贝输入数据到 pinned buffer
memcpy(h_pinned_in, h_input, n * sizeof(float));
// 异步传输 + 计算流水线
musaMemcpyAsync(d_input, h_pinned_in, n,
musaMemcpyHostToDevice, stream);
processKernel<<<grid, block, 0, stream>>>(d_input, d_output);
musaMemcpyAsync(h_pinned_out, d_output, n,
musaMemcpyDeviceToHost, stream);
// 等待完成
musaStreamSynchronize(stream);
// 拷贝结果
memcpy(h_output, h_pinned_out, n * sizeof(float));
// 清理
musaFreeHost(h_pinned_in);
musaFreeHost(h_pinned_out);
musaFree(d_input);
musaFree(d_output);
musaStreamDestroy(stream);
}
可移植页锁定内存(零拷贝,Zero-Copy)
// 分配可移植 pinned memory(支持多 GPU)
float* h_mapped;
musaMallocHost(&h_mapped, size, musaHostAllocMapped);
// 获取设备指针
float* d_mapped;
musaHostGetDevicePointer(&d_mapped, h_mapped, 0);
// 直接在 kernel 中使用(零拷贝)
__global__ void zeroCopyKernel(float* data) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < 1000000) {
data[idx] = data[idx] * 2.0f;
}
}
zeroCopyKernel<<<grid, block>>>(d_mapped);
musaDeviceSynchronize();
musaFreeHost(h_mapped);
零拷贝内存
零拷贝基础
零拷贝允许 GPU 直接访问主机内存,无需显式拷贝:
#include <musa.h>
#include <stdio.h>
#define N 1000000
__global__ void zeroCopyKernel(float* data, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < n) {
data[idx] = data[idx] * 2.0f + 1.0f;
}
}
int main() {
size_t size = N * sizeof(float);
// 分配 mapped pinned memory
float* h_data;
musaMallocHost(&h_data, size, musaHostAllocMapped);
// 获取设备指针
float* d_data;
musaHostGetDevicePointer(&d_data, h_data, 0);
// CPU 初始化
for (int i = 0; i < N; i++) {
h_data[i] = float(i);
}
// GPU 处理(直接访问主机内存)
dim3 blockSize(256);
dim3 gridSize((N + blockSize.x - 1) / blockSize.x);
zeroCopyKernel<<<gridSize, blockSize>>>(d_data, N);
musaDeviceSynchronize();
// CPU 读取结果(无需拷贝)
printf("Result[0] = %f\n", h_data[0]);
musaFreeHost(h_data);
return 0;
}