¿Cómo devolver una sola variable desde una función del kernel CUDA?

2 minutos de lectura

avatar de usuario
BCD Pouya

Tengo una función de búsqueda CUDA que calcula una sola variable. ¿Cómo puedo devolverlo?

__global__ 
void G_SearchByNameID(node* Node, long nodeCount, long start,char* dest, long answer){
    answer = 2;
}

cudaMemcpy(h_answer, d_answer, sizeof(long), cudaMemcpyDeviceToHost);
cudaFree(d_answer);

para ambas líneas obtengo este error: error: el argumento de tipo “largo” es incompatible con el parámetro de tipo “const void *”

he estado usando __device__ variables para este propósito, de esa manera no tiene que molestarse con cudaMalloc y cudaFree y no tiene que pasar un puntero como argumento del kernel, lo que le ahorra un registro en su kernel para arrancar.

__device__ long d_answer;

__global__ void G_SearchByNameID() {
  d_answer = 2;
}

int main() {
  SearchByNameID<<<1,1>>>();
  typeof(d_answer) answer;
  cudaMemcpyFromSymbol(&answer, "d_answer", sizeof(answer), 0, cudaMemcpyDeviceToHost);
  printf("answer: %d\n", answer);
  return 0;
}

  • @Erogol, tanto el kernel como el código del host conocen el tipo del __device__ declaración

    – cuál

    8 de marzo de 2013 a las 23:48

  • Por alguna razón, esto solo funciona para mí (Toolkit 6.5) si reemplazo "d_answer" con d_answer, es decir, quitar las comillas. Aparte de eso, esto funciona bien.

    – icurays1

    26 de mayo de 2015 a las 7:41

  • El valor siempre regresa como cero para mí.

    – orodbhen

    5 de septiembre de 2016 a las 11:06

  • ¿Puede un __device__ variable ser subproceso local? Las variables globales como esa no funcionan para aplicaciones multiproceso.

    – Serge Rogatch

    10/09/2016 a las 19:15

  • Este enfoque no es “reentrante”, en el sentido de que no admite lanzamientos del mismo kernel desde múltiples flujos.

    – einpoklum

    31 de mayo de 2019 a las 22:19

Para obtener un solo resultado, debe Memcpy, es decir:

#include <assert.h>

__global__ void g_singleAnswer(long* answer){ *answer = 2; }

int main(){

  long h_answer;
  long* d_answer;
  cudaMalloc(&d_answer, sizeof(long));
  g_singleAnswer<<<1,1>>>(d_answer);
  cudaMemcpy(&h_answer, d_answer, sizeof(long), cudaMemcpyDeviceToHost); 
  cudaFree(d_answer);
  assert(h_answer == 2);
  return 0;
}

Supongo que el error se debe a que está pasando un valor largo, en lugar de un puntero a un valor largo.

  • tu no tener a memcpy() – hay otras opciones, como la respuesta de @wich. -1 a menos que argumente que copiar es la mejor / única opción realista.

    – einpoklum

    31 de mayo de 2019 a las 22:19

  • Tenga en cuenta que la otra opción lo hace hacer un memcpy (está en el nombre cudaMemcpyFromSymbol). Esta respuesta usa la asignación dinámica, que es preferible para aplicaciones de subprocesos múltiples frente a la otra que usa una variable global.

    – rgov

    29 de febrero de 2020 a las 2:49

¿Ha sido útil esta solución?