Cuda 将并发和GPU理解为有限的资源

Cuda 将并发和GPU理解为有限的资源,cuda,opencl,theory,gpgpu,Cuda,Opencl,Theory,Gpgpu,有了CPU和内存,这很简单 一个进程有一个很大的虚拟地址空间,部分映射到物理内存中。当当前进程尝试访问不在物理内存中的页面时,操作系统会介入,选择要交换的页面(例如使用循环),将其交换到光盘中,然后从交换中读取所需页面,然后将控件返回到进程。这很简单,因为如果没有该页面,流程将无法继续 GPU内核则是另一回事 我们考虑一个用例: 一个高优先级的[cpu]进程,即X,调用内核,这是一个阻塞调用。此时,操作系统切换上下文并将CPU分配给另一个进程是合理的,即Z。为了举例说明,让进程Z也对GPU执行一

有了CPU和内存,这很简单

一个进程有一个很大的虚拟地址空间,部分映射到物理内存中。当当前进程尝试访问不在物理内存中的页面时,操作系统会介入,选择要交换的页面(例如使用循环),将其交换到光盘中,然后从交换中读取所需页面,然后将控件返回到进程。这很简单,因为如果没有该页面,流程将无法继续

GPU内核则是另一回事

我们考虑一个用例: 一个高优先级的[cpu]进程,即X,调用内核,这是一个阻塞调用。此时,操作系统切换上下文并将CPU分配给另一个进程是合理的,即Z。为了举例说明,让进程Z也对GPU执行一些繁重的操作


现在,GPU驱动程序做什么?它会停止属于[更高优先级]X的内核吗?它是否告知操作系统Z的优先级不足以卸载X的内核?一般来说,当两个进程需要GPU资源,但可用的GPU内存足以一次只为其中一个进程提供服务时,会发生什么情况?

CUDA GPU上下文以粗粒度协同切换—比如memcpy或内核启动。如果两个上下文都有足够的内存,那么硬件很乐意在它们之间协作切换上下文,而性能代价很小。但是因为它是协作的,长时间运行的内核会干扰其他内核的执行

现代GPU确实支持虚拟内存,即通过地址转换保护内存,但不支持按需分页。这意味着GPU设备内存和映射的固定内存可访问的每一块内存都必须在分配后物理存在并映射


Windows Vista中引入的Windows显示驱动程序WDDM以非常粗的粒度进行分页。驱动程序需要跟踪执行给定命令缓冲区所需的内存对象,操作系统确保它们存在。操作系统可以在不需要时将它们交换出去。CUDA的缺点是,由于指针可以存储,所有与CUDA地址空间相关联的内存对象都必须驻留才能运行CUDA内核。因此,分页对于CUDA的效果不如WDDM设计用于运行的图形应用程序好。

CUDA GPU上下文以粗粒度协同切换,如memcpy或内核启动。如果两个上下文都有足够的内存,那么硬件很乐意在它们之间协作切换上下文,而性能代价很小。但是因为它是协作的,长时间运行的内核会干扰其他内核的执行

现代GPU确实支持虚拟内存,即通过地址转换保护内存,但不支持按需分页。这意味着GPU设备内存和映射的固定内存可访问的每一块内存都必须在分配后物理存在并映射


Windows Vista中引入的Windows显示驱动程序WDDM以非常粗的粒度进行分页。驱动程序需要跟踪执行给定命令缓冲区所需的内存对象,操作系统确保它们存在。操作系统可以在不需要时将它们交换出去。CUDA的缺点是,由于指针可以存储,所有与CUDA地址空间相关联的内存对象都必须驻留才能运行CUDA内核。因此,分页对CUDA的效果不如对图形应用程序的效果好,WDDM设计用于运行图形应用程序。

如果给opencl上下文一个完整的cpu,即使是一个数据传送线程也会使opencl的cpu核心在一段时间内不可用。您可以使用opencl的设备裂变,将一个完整的cpu划分为单独的内核,以消除这种情况。目前,也许gtx泰坦和r9-290x能够进行设备裂变。在FX8150上测试了HD7870驱动程序的opencl,它被阻塞了。当我用裂变装置分离7个核时,它像流体一样流动。如果你不在gpu上使用waitevent,那么内核就不会阻塞cpu。我听说HD7870可以在一个处理器中单独完成与计算单元编号20一样多的独立任务folding@home地点实际上,正如他们所写的,两个或三个计算单元的输入可以由一个内核完成。内核调用是非阻塞的。2.您可以启动多个内核,并按顺序或可能并行执行,即使是从多个线程发出,它们将根据GPU调度程序的规则3执行。如果试图分配的内存超过设备支持的数量,则分配将失败并返回运行时API错误。因此,您甚至无法启动依赖于这些数据的内核。让我们假设GPU有1GB的RAM。进程A需要700 Mb才能完成其任务,进程B需要700 Mb才能完成其任务。会发生什么?在每个进程开始之前,必须显式地分配内存,我们
为CUDA准备Cudamaloc。CPU上的进程A第一次尝试执行cudaMalloc将成功700MB。进程B的第二次尝试(假设第一次尝试没有使用cudaFree释放)将失败。如果您注意到这些API错误,那么您的代码永远不会到达与进程B中的第二次分配相关联的内核启动点。如果您为opencl上下文提供了一个完整的cpu,则即使是单个数据馈送线程也会使opencl的cpu内核在一段时间内不可用。您可以使用opencl的设备裂变,将一个完整的cpu划分为单独的内核,以消除这种情况。目前,也许gtx泰坦和r9-290x能够进行设备裂变。在FX8150上测试了HD7870驱动程序的opencl,它被阻塞了。当我用裂变装置分离7个核时,它像流体一样流动。如果你不在gpu上使用waitevent,那么内核就不会阻塞cpu。我听说HD7870可以在一个处理器中单独完成与计算单元编号20一样多的独立任务folding@home地点实际上,正如他们所写的,两个或三个计算单元的输入可以由一个内核完成。内核调用是非阻塞的。2.您可以启动多个内核,并按顺序或可能并行执行,即使是从多个线程发出,它们将根据GPU调度程序的规则3执行。如果试图分配的内存超过设备支持的数量,则分配将失败并返回运行时API错误。因此,您甚至无法启动依赖于这些数据的内核。让我们假设GPU有1GB的RAM。进程A需要700 Mb才能完成其任务,进程B需要700 Mb才能完成其任务。会发生什么?在每个进程开始之前,必须使用CUDA的cudaMalloc显式分配内存。CPU上的进程A第一次尝试执行cudaMalloc将成功700MB。进程B的第二次尝试(假设第一次尝试没有使用cudaFree释放)将失败。如果您注意这些API错误,那么您的代码永远不会到达与进程B中的第二次分配相关联的内核启动点。