Я хочу использовать Page-locked Host memory
в CUDA для обмена сообщениями между ХОСТОМ и УСТРОЙСТВОМ. Позвольте мне выразить свои идеи на следующих примерах. Я не уверен, разумно ли это.
Окружение моей машины:
- Ubuntu 14.04.5 LTS
- gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
- CUDA 9.1
Я разделил свою программу на четыре шага, как показано ниже:
- Предположим, что есть два блока, и для первого блока он выполняет некоторые вычисления, и в конце первого генерируется сигнал.
блок;
- Когда первый блок завершает функцию, он информирует терминал ЦП, а затем соответствующие данные организуются в ЦП;
- Затем скопируйте данные в GPU и подайте GPU сигнал, когда копирование данных будет завершено;
- Второй блок в gpu запускается на основе сигнала на шаге 3.
После того, как вы узнали о том, что я хочу сделать, У меня проблема в том, что когда я изменяю данные в памяти, заблокированной на странице (в моей программе есть сигнал), кажется, что они не могут быть идентифицированы противоположное устройство.
Для этого вопроса я попробовал следующее
- Я обнаружил, что компилятор CUDA может оптимизировать значение и сохранить значение в регистре, поэтому я не могу получить самое новое значение в ядре, поэтому я заметил PTX.
- Я попытался использовать PTX для предотвращения оптимизации компилятором части кода, и я успешно получил сигнал в ядре, , но не смог передать устройство с формой сигнала на хост , что сбило с толку мне очень.
Часть кода моего проекта показана ниже:
__global__ void pipeline(int *flag_a, int*flag_b, int*Input, int*Out){
int idx = threadIdx.x;
if (blockIdx.x == 0) {
if (0 == idx) {
flag_a[0] = 1; //to generate signal in the step one
//why the host cannot get the flag_a[0]==1?
}
}
if (blockIdx.x == 1) {
if (0 == idx) {
int value = 0;
do{
asm volatile("ld.global.cg.u32 %0, [%1];" :"=r"(value) : "l"(&flag_b[0]));
//receipt signal form the host generate in step 3
//and the asm volatile to make sure I can get the newest flag_b[0]
} while (value != 1);
}
__syncthreads();
Out[idx] = Input[idx] + idx;
}
}
int main()
{
/*1*/
int *flag_a, *flag_b;
cudaHostAlloc((void**)&flag_a, sizeof(int), cudaHostAllocMapped);
cudaHostAlloc((void**)&flag_b, sizeof(int), cudaHostAllocMapped);
flag_a[0] = 0;
flag_b[0] = 0;
/*2*/
int*Input, *Out;
int *d_Input, *d_Out;
int*d_float_a, *d_float_b;
Input = (int*)malloc(sizeof(int) * 32);
Out = (int*)malloc(sizeof(int) * 32);
for (int i = 0; i<32; i++) {
Input[i] = i;
}
memset(Out, 0, sizeof(int) * 32);
cudaMalloc((void**)&d_Input, sizeof(int) * 32);
cudaMemset(d_Input, 0, sizeof(int) * 32);
cudaMalloc((void**)&d_Out, sizeof(int) * 32);
cudaMemset(d_Out, 0, sizeof(int) * 32);
cudaHostGetDevicePointer((void **)&d_float_a, (void *)flag_a, 0);
cudaHostGetDevicePointer((void **)&d_float_b, (void *)flag_b, 0);
cudaStream_t stream_kernel, stream_datacopy;
cudaStreamCreate(&stream_kernel);
cudaStreamCreate(&stream_datacopy);
pipeline <<< 2, 32, 0, stream_kernel >>> (d_float_a, d_float_b, d_Input, d_Out);
int count = 0;
do{
if (flag_a[0]==1){
cudaMemcpyAsync(d_Input, Input, sizeof(int) * 32, cudaMemcpyHostToDevice, stream_datacopy);
cudaStreamSynchronize(stream_datacopy);
flag_b[0] = 1; //step 3;
break;
}
if (count==10)
break;
} while (1 != flag_a[0]);
cudaStreamSynchronize(stream_kernel);
cudaMemcpy(Out, d_Out, sizeof(int) * 32, cudaMemcpyDeviceToHost);
for (int i = 0; i<32; i++) {
printf("%d:%d\n", i, Out[i]);
}
// free()
return 0;
}
Я не очень хорош в программировании на CUDA, и я не уверен, что это правильный путь для переключения сигнала между хостом и устройством, все, что я сделал, это просто попытка, и если кто-то может дать мне совет, я буду признателен , Заранее спасибо :)