以下是针对2.1.3 Memory in GPU Computing章节内容设计的知识巩固练习题包含选择题、填空题、简答题和代码分析题。2.1.3 GPU内存管理知识巩固练习题一、选择题每题只有一个正确答案1. 关于统一内存Unified Memory下列说法正确的是A. 统一内存只能从GPU访问CPU无法访问B. 统一内存需要程序员手动使用cudaMemcpy进行数据传输C. 统一内存由NVIDIA驱动程序自动管理主机和设备间的数据迁移D. 统一内存只能在Linux系统上使用2. 以下哪个API用于分配统一内存A.cudaMalloc()B.cudaMallocHost()C.cudaMallocManaged()D.malloc()3. 关于cudaMallocHost()函数下列说法错误的是A. 分配的是主机端的页锁定内存B. 可以提升主机与设备间的数据传输性能C. 分配的内存只能由CPU访问GPU无法直接访问D. 分配的内存会自动迁移到GPU4. 以下哪个API用于将数据从主机拷贝到设备A.cudaMalloc()B.cudaMemcpy()且方向参数为cudaMemcpyDeviceToHostC.cudaMemcpy()且方向参数为cudaMemcpyHostToDeviceD.cudaMemset()5. 关于cudaMemcpy()函数的特性下列说法正确的是A. 该函数是异步的调用后立即返回B. 该函数是同步的返回时拷贝操作已完成C. 该函数只能用于主机到设备的拷贝D. 该函数不需要指定拷贝方向6. 在显式内存管理中对于将频繁用于GPU数据传输的主机缓冲区最佳实践是使用A.malloc()B.cudaMalloc()C.cudaMallocHost()D.new操作符7. 以下哪个API用于释放通过cudaMallocHost()分配的内存A.free()B.cudaFree()C.cudaFreeHost()D.delete8. 关于页锁定内存Page-Locked Memory下列说法正确的是A. 分配越多页锁定内存系统性能越好B. 页锁定内存只能由GPU访问C. 页锁定内存可以提升数据传输性能但分配过多可能降低系统性能D. 页锁定内存不需要专门释放9. 以下哪项不是显式内存管理的优势A. 代码更简洁易写B. 可以精确控制数据拷贝时机C. 可以明确指定内存分配位置D. 可以将数据传输与计算重叠10. 在统一内存模型中如果需要等待内核执行完成应使用哪个函数A.cudaMemcpy()B.cudaDeviceSynchronize()C.cudaFree()D.cudaMallocManaged()二、填空题**1. 统一内存通过_____API分配通过_____API释放。**2. 除了cudaMallocManaged()还可以使用_____声明说明符来创建统一内存变量。**3. 显式内存管理中分配设备内存使用_____API分配主机页锁定内存使用_____API。**4.cudaMemcpy()函数的最后一个参数用于指定_____其中cudaMemcpyDefault表示_____。**5. 在显式内存管理示例中内核启动时使用的指针是_____填A/devA等因为内核需要在_____上执行。**6.cudaMemcpy()函数是_____同步/异步的这意味着函数返回时数据传输_____已完成/可能未完成。**7. 页锁定内存也被称为_____使用cudaMallocHost()分配的内存应使用_____释放。**8. 为了优化统一内存的性能CUDA提供了_____和_____等API向驱动程序提供内存使用提示。**9. 在显式内存管理示例中使用_____函数将设备内存初始化为0。**10. 如果系统支持自动统一内存如某些Linux系统则无需使用_____或_____说明符。三、简答题1. 简述统一内存Unified Memory的核心概念和主要优点。2. 比较统一内存和显式内存管理的优缺点并说明各自适用的场景。3. 什么是页锁定内存Page-Locked Memory它有什么优点和使用注意事项4. 描述显式内存管理的基本工作流程从内存分配到数据回传。5. 解释为什么在显式内存管理示例中使用cudaMallocHost()而不是malloc()来分配主机内存。四、代码分析题1. 阅读以下代码找出其中的错误并说明原因voidexample1(intvectorLength){float*A,*B,*C;// 分配内存cudaMallocManaged(A,vectorLength*sizeof(float));cudaMalloc(B,vectorLength*sizeof(float));cudaMallocHost(C,vectorLength*sizeof(float));// 初始化数据initArray(A,vectorLength);// 在主机端初始化AinitArray(B,vectorLength);// 在主机端初始化B?initArray(C,vectorLength);// 在主机端初始化C// 启动内核vecAdd256,256(A,B,C,vectorLength);// 释放内存cudaFree(A);cudaFree(B);cudaFreeHost(C);}2. 阅读以下显式内存管理代码补充缺失的部分voidexplicitMemExample(intvectorLength){// 主机指针float*A,*B,*C;// 设备指针float*devA,*devB,*devC;// 1. 分配主机页锁定内存cudaMallocHost(A,vectorLength*sizeof(float));cudaMallocHost(B,vectorLength*sizeof(float));cudaMallocHost(C,vectorLength*sizeof(float));// 2. 初始化主机数据initArray(A,vectorLength);initArray(B,vectorLength);// 3. 分配设备内存// 请补充代码// 4. 将数据从主机拷贝到设备// 请补充代码// 5. 启动内核intthreads256;intblocks(vectorLengththreads-1)/threads;vecAddblocks,threads(devA,devB,devC,vectorLength);// 6. 等待内核完成// 请补充代码// 7. 将结果从设备拷贝回主机// 请补充代码// 8. 释放内存cudaFree(devA);cudaFree(devB);cudaFree(devC);cudaFreeHost(A);cudaFreeHost(B);cudaFreeHost(C);}3. 分析以下两种内存管理方式的代码差异并说明各自的优缺点方式A统一内存cudaMallocManaged(A,N*sizeof(float));cudaMallocManaged(B,N*sizeof(float));cudaMallocManaged(C,N*sizeof(float));initArray(A,N);initArray(B,N);vecAddblocks,threads(A,B,C,N);cudaDeviceSynchronize();方式B显式内存管理cudaMallocHost(A,N*sizeof(float));cudaMallocHost(B,N*sizeof(float));cudaMallocHost(C,N*sizeof(float));cudaMalloc(devA,N*sizeof(float));cudaMalloc(devB,N*sizeof(float));cudaMalloc(devC,N*sizeof(float));initArray(A,N);initArray(B,N);cudaMemcpy(devA,A,N*sizeof(float),cudaMemcpyHostToDevice);cudaMemcpy(devB,B,N*sizeof(float),cudaMemcpyHostToDevice);vecAddblocks,threads(devA,devB,devC,N);cudaDeviceSynchronize();cudaMemcpy(C,devC,N*sizeof(float),cudaMemcpyDeviceToHost);参考答案一、选择题答案C统一内存由驱动程序自动管理数据迁移CcudaMallocManaged用于分配统一内存DcudaMallocHost分配的内存不会自动迁移到GPUCcudaMemcpyHostToDevice表示主机到设备BcudaMemcpy是同步的CcudaMallocHost分配页锁定内存是最佳实践CcudaFreeHost释放页锁定内存C页锁定内存提升性能但过多会降低系统性能A显式内存管理代码更冗长不是更简洁BcudaDeviceSynchronize等待设备完成二、填空题答案cudaMallocManaged()cudaFree()__managed__cudaMalloc()cudaMallocHost()拷贝方向自动根据指针确定传输类型devAGPU同步已完成钉住内存pinned memorycudaFreeHost()内存建议Memory Advise预取PrefetchcudaMemset()cudaMallocManaged()__managed__三、简答题答案要点1. 统一内存的核心概念和优点核心概念驱动程序自动管理主机和设备间的数据迁移优点简化编程、减少显式数据传输代码、按需自动迁移、提高开发效率2. 统一内存 vs 显式内存管理统一内存优点编程简单、代码简洁、适合快速原型开发统一内存缺点性能控制粒度较粗显式内存优点性能优化空间大、可精确控制数据传输时机和位置显式内存缺点代码冗长、编程复杂度高适用场景统一内存适合开发初期和简单应用显式管理适合追求极致性能的复杂应用3. 页锁定内存定义主机端不会被操作系统换出到磁盘的内存优点提升GPU数据传输性能、支持异步传输注意事项分配过多可能降低系统整体性能应仅对GPU传输缓冲区使用4. 显式内存管理工作流程分配主机内存最佳使用页锁定内存分配设备内存将数据从主机拷贝到设备启动内核使用设备指针等待内核完成将结果从设备拷贝回主机释放所有分配的内存5. 使用cudaMallocHost而不是malloc的原因提供更好的数据传输性能支持异步内存传输避免页错误和额外的拷贝操作是CUDA编程中与GPU频繁传输数据的最佳实践四、代码分析题答案1. 代码错误分析错误1B使用cudaMalloc()分配这是设备内存但后续initArray(B, ...)在主机端初始化设备指针不能在主机端直接访问错误2C使用cudaMallocHost()分配这是主机内存但内核启动时传入了C内核无法直接访问主机内存修正所有指针应使用相同的内存分配方式或显式管理时明确区分主机指针和设备指针2. 补充代码// 3. 分配设备内存cudaMalloc(devA,vectorLength*sizeof(float));cudaMalloc(devB,vectorLength*sizeof(float));cudaMalloc(devC,vectorLength*sizeof(float));// 4. 将数据从主机拷贝到设备cudaMemcpy(devA,A,vectorLength*sizeof(float),cudaMemcpyHostToDevice);cudaMemcpy(devB,B,vectorLength*sizeof(float),cudaMemcpyHostToDevice);cudaMemset(devC,0,vectorLength*sizeof(float));// 6. 等待内核完成cudaDeviceSynchronize();// 7. 将结果从设备拷贝回主机cudaMemcpy(C,devC,vectorLength*sizeof(float),cudaMemcpyDeviceToHost);3. 两种方式的优缺点分析方式A统一内存优点代码简洁只需分配内存无需显式数据传输开发效率高易于理解和维护适合快速原型开发和简单应用方式A统一内存缺点数据传输时机由驱动程序控制优化空间有限可能产生不必要的页面错误和数据迁移方式B显式管理优点精确控制数据何时传输、传输到哪里可以重叠数据传输与计算使用页锁定内存提升传输性能适合性能敏感型应用方式B显式管理缺点代码冗长需要显式管理主机和设备指针开发复杂度高容易出错需要深入理解内存层次结构