将CUDA 5与VS 2012和功能3.5(Titan和K20)配合使用。
在我的内核执行的特定阶段,我想将生成的数据块发送到主机内存并通知主机数据已准备就绪,因此主机将对其进行操作。
我不能等到内核执行结束才能从设备读回数据,因为:
你能否指出我必须走的道路以及我必须用来实现我的要求的可能的概念和功能?简而言之,我如何写入主机并通知主机块数据是否已准备好进行主机处理?
N.B。每个线程不与任何其他线程共享任何生成的数据,它们独立运行。所以,据我所知(如果我错了请纠正我),块,线程和warp的概念不会影响这个问题。或者换句话说,如果他们帮助回答,我可以自由地改变他们的组合。
以下示例代码显示我正在尝试执行此操作:
#pragma once
#include <conio.h>
#include <cstdio>
#include <cuda_runtime_api.h>
__global__ void Kernel(size_t length, float* hResult)
{
int tid = threadIdx.x + blockIdx.x * blockDim.x;
// Processing multiple data chunks
for(int i = 0;i < length;i++)
{
// Once this is assigned, I don't need it on the device anymore.
hResult[i + (tid * length)] = i * 100;
}
}
void main()
{
size_t length = 10;
size_t threads = 2;
float* hResult;
// An array that will hold all data from all threads
cudaMallocHost((void**)&hResult, threads * length * sizeof(float));
Kernel<<<threads,1>>>(length, hResult);
// I DO NOT want to wait to the end and block to get the data
cudaError_t error = cudaDeviceSynchronize();
if (error != cudaSuccess) { throw error; }
for(int i = 0;i < threads * length;i++)
{
printf("%f\n", hResult[i]);;
}
cudaFreeHost(hResult);
system("pause");
}
答案 0 :(得分:2)
在高级别,在设备上:
cudaMalloc
分配)或直接写入主机内存(之前使用cudaHostAlloc
分配)threadfence()
(如果您正在使用设备全局内存)或threadfence_system()
调用(如果使用主机内存)在主持人身上:
请注意,即使使用上述过程,如果从多个线程块生成/创建数据,仍然需要隐含的设备范围同步。可用的唯一直接的设备范围同步是内核启动(或特别是内核的完成)。从单个线程块复制数据只会将设备范围内同步的要求移出此特定序列(到此序列之前的某个位置)。
你给出的理由并没有真正告诉我,代码无法重构,无法通过内核启动基础在内核启动时创建数据,这样可以巧妙地解决这些问题并消除对上述过程的需求同样。
编辑:回复评论中的问题。 在没有具体示例的情况下,很难更具体地说明如何重构代码以便为每个内核调用提供一个数据块。
让我们看一个图像处理案例,其中我有一个30帧的视频序列存储在全局存储器中。内核将根据某种算法处理每个帧,然后将处理后的数据提供给主机。
在您的提议中,在内核完成处理帧之后,它可以向主机发信号通知数据已就绪,然后继续处理下一帧。问题是,如果帧由多个线程块处理,则没有简单的方法来知道何时完成所有线程块处理该帧。可能需要设备范围的同步屏障,但除了通过内核调用机制之外,它并不方便。但是,大概在这样的内核中我们可能会有这样的序列:
在重构方法中,我们将循环移出内核,以托管代码:
通过执行此操作,内核标记了显示帧处理何时完成所需的显式同步,并且可以使用数据。