2011-06-14 9 views
7

He estado intentando crear kernels de plantillas, pero he tenido problemas para llamarlos a mi programa. Tengo una clase Matrix<T> plantilla, y algunos métodos definidos dentro de élProblema al llamar a la plantilla kernel CUDA

Matrix.h:

template <typename T> class Matrix { 
    ... 
    void sum(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum); 
    ... 
} 

#include "Matrix.cu" 

Matrix.cu:

#include "MatrixKernel.h" 

template<typename T> void Matrix<T>::sum(const Matrix<T>& m, Matrix<T>& sum) { 
    ... 
    sumKernel<T><<<dimGrid, dimBlock>>>(Matrix<T> m1, Matrix<T> m2, Matrix<T> sum) 
    ... 
} 

MatrixKernel.h:

template<typename T> __global__ void sumKernel(const Matrix<T> m1, const Matrix<T> m2, Matrix<T> sum) { 
... 
} 

El problema es que cuando invoco sumKernel desde el interior de la suma, el compilador me da el siguiente error:

error C2059: syntax error : '<' 

¿Alguien sabe lo que está pasando? El código compilado bien justo antes de incluir la llamada sumKernel.

Gracias.

+0

No sabía que pudiera usar CUDA y C++ (!). Sugerencia trivial: intente poner un espacio entre '' y '<<<' en caso de que ejecutarlos juntos esté causando problemas de análisis. – Rup

+0

¿Le dijo el compilador en qué línea está el error? Hay muchos

+0

@Rup: sí, puedes. Incluso puede pasar objetos como argumentos a los núcleos (siempre que haya copiado los datos de interés en la memoria del dispositivo). Voy a intentar tu sugerencia también. @Bomadeno: el error está en la línea que realiza la llamada al kernel. – Renan

Respuesta

6

Parece que tiene un #include extraño, lo que hace que el código compilado por el compilador incorrecto. Haga una distinción entre los encabezados gpu y los encabezados de la CPU usando .cu.h para encabezados cuda. Asegúrese de solo NVCC compila .cu y .cu.h archivos. Los archivos Cuda nunca deberían incluirse en archivos cpp. La llamada al kernel y kernel debe estar en los archivos .cu o .cu.h, y esos archivos no se deben incluir en ningún lado en cpps.

Debido a que su .cu está siendo incluido en una cabecera que está siendo compilado por el compilador de acogida, el compilador de acogida termina golpeando el token <<< - el cual no reconoce. Probablemente no entienda el token << por lo que consume eso, dejando un inesperado <.

Aquí es una forma alternativa de hacer las cosas que deben trabajar (no lo intentó pero es similar al código que utilizamos)

(nota, esto podría funcionar, pero también podría no ser el camino correcto para resolver el problema . Mi jefe no le gusta como solución y preferiría agregar una implementación por variación)

El problema subyacente parece ser la falta de distinción entre el host y el código del dispositivo. Dejo el detalle en mi solución: cosas como copiar resultados desde y hacia el dispositivo, implementación de suma, etc.

El problema que estoy tratando de resolver es, dado un constructo, cómo se puede moldear para usar ambos en el host y el dispositivo?

Voy a la plantilla Matrix.h tanto en el tipo como en los detalles de implementación.

template <typename T, typename Implementation<T> > class Matrix { 
    void sum(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum) 
    { 
     Implementation.sumImp(m1, m2, sum); 
    } 
} 

La aplicación de host, HostMatrixSum.h va a hacer las cosas los de la CPU:

#include "Matrix.h" 

template <typename T> struct HostMatrixSum 
{ 
    void sumImp(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum) 
    { 
     ... 
    } 
} 

Mientras GpuMatrixSum.cu.h va a cargar la matriz, hacer la suma y recuperar los resultados:

#include "Matrix.h" 

template <typename T> struct GpuMatrixSum 
{ 
    template<typename T> __global__ void sumKernel(const Matrix<T> m1, const Matrix<T> m2, Matrix<T> sum) 
    { 
     ... 
    } 

    void sumImp(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum) 
    { 
     ... 
     sumKernel<T> <<< dimGrid, dimBlock >>> (m1,m2); 
     ... 
    } 
} 

Entonces cuando utilizamos Matrix desde el código de host, utilizamos la plantilla en la implementación de la suma de host y nunca necesitamos ver ninguna especificación de cuda:

#include "Matrix.h" 
#include "HostMatrixSum.h" 

Matrix<int, HostMatrixSum> m1 = Matrix<int>(...); 
Matrix<int, HostMatrixSum> m2 = Matrix<int>(...); 
Matrix<int, HostMatrixSum> result; 
Matrix.sum(m1,m2,result); 

Y si estamos trabajando en la GPU podemos utilizar la aplicación GPU acelerada de la suma:

#include "Matrix.h" 
#include "GpuMatrixSum.cu.h" 

Matrix<int, GpuMatrixSum> m1 = Matrix<int>(...); 
Matrix<int, GpuMatrixSum> m2 = Matrix<int>(...); 
Matrix<int, GpuMatrixSum> result; 
Matrix.sum(m1,m2,result); 

la esperanza de que funcione para usted!

+0

Voy a intentar eso. Pero al mismo tiempo, parece extraño que en MatrixKernel.h, por ejemplo, el compilador no se queje de la palabra clave __global__ (que solo puede significar que NVCC la está compilando, ¿no?) Otra cosa: si lo que dices en realidad es el problema, ¿dónde implementaría el método de suma? Si no escribo '#include "Matrix.cu"' dentro de "Matrix.h", habrá un error de enlace, porque la plantilla debe declararse y definirse en el mismo archivo ... – Renan

+0

Creo que tenía razón , Tuve que olvidarme de implementar Matrix como una clase de plantilla, porque no había manera de que pudiera hacerlo funcionar de esa manera. Si incluyo, por ejemplo, un archivo .cu en el encabezado, todos los demás archivos que incluyan el encabezado Matrix también incluirán .cu, incluso .cpp, lo que inevitablemente dará lugar a un error de compilación. Usar núcleos de plantilla está bien, pero hacer los métodos de C++ que los llaman plantillas tampoco es posible debido a lo que acabo de explicar. Después de todo, es un poco complicado ... – Renan

+0

Dado que MatrixKernel.h solo está incluido en un archivo cu, solo nvcc lo incluye. Si incluyó MatrixKernel.h en un archivo cpp de host, sospecho que se caería. Nombro los encabezados específicos de cuda .cu.h para aclarar que solo es para inclusión desde archivos .cu. Estoy trabajando en una respuesta a la parte de "cómo hacerlo", tratando de encontrar una solución elegante :) –

1

que tenían el mismo problema: error C2059: error de sintaxis: '<'

En primer lugar, he encontrado una buena puesta a punto/tutorial aquí (por expreso visual 2010 y CUDA 4.0): http://www.stevenmarkford.com/installing-nvidia-cuda-with-visual-studio-2010/

y para resolver el problema de error de sintaxis, esto lo resolvió: How do I start a CUDA app in Visual Studio 2010?

en concreto, el cambio de la propiedad del archivo * br tal que: Tipo se establece en "CUDA C/C++"

Finalmente funcionó para mí.

Cuestiones relacionadas