2012-03-10 5 views
3

Я пытаюсь изменить простой динамический вектор в CUDA, используя базовую библиотеку CUDA. Но на экране появляется сообщение «launch_closure_by_value», в котором указывается, что ошибка связана с некоторым процессом синхронизации.Как решить библиотеку CUDA Thrust - ошибка синхронизации for_each?

Простая 1D динамическая модификация массива невозможна из-за этой ошибки.

Мой сегмент кода, вызывающий ошибку, выглядит следующим образом.

из .cpp файла, который я называю setIndexedGrid, который определен в System.cu

float* a= (float*)(malloc(8*sizeof(float))); 
a[0]= 0; a[1]= 1; a[2]= 2; a[3]= 3; a[4]= 4; a[5]= 5; a[6]= 6; a[7]= 7; 
float* b = (float*)(malloc(8*sizeof(float))); 
setIndexedGridInfo(a,b); 

Код сегмента в System.cu:

void 
setIndexedGridInfo(float* a, float*b) 
{ 

    thrust::device_ptr<float> d_oldData(a); 
    thrust::device_ptr<float> d_newData(b); 

    float c = 0.0; 

    thrust::for_each(
     thrust::make_zip_iterator(thrust::make_tuple(d_oldData,d_newData)), 
     thrust::make_zip_iterator(thrust::make_tuple(d_oldData+8,d_newData+8)), 
     grid_functor(c)); 
} 

grid_functor определяется в _kernel.cu

struct grid_functor 
{ 
    float a; 

    __host__ __device__ 
    grid_functor(float grid_Info) : a(grid_Info) {} 

    template <typename Tuple> 
    __device__ 
    void operator()(Tuple t) 
    { 
     volatile float data = thrust::get<0>(t); 
     float pos = data + 0.1; 
     thrust::get<1>(t) = pos; 
    } 

}; 

Я также получаю их в окне вывода (я использую Visual Studio):

первого шанса исключение в 0x000007fefdc7cacd в Particles.exe: Microsoft C++ исключение: cudaError_enum в ячейке памяти 0x0029eb60 .. Во-первых, вероятность исключения на 0x000007fefdc7cacd в smokeParticles.exe: Microsoft C++ исключение: тяга :: система :: system_error в ячейке памяти 0x0029ecf0 .. необработанное исключением в 0x000007fefdc7cacd в Particles.exe: Microsoft C++ исключение: тяга :: система :: system_error в ячейке памяти 0x0029ecf0 ..

Что вызывает проблема?

ответ

5

Вы пытаетесь использовать указатели памяти хоста в функциях, ожидающих указатели в памяти устройства. Этот код является проблемой:

float* a= (float*)(malloc(8*sizeof(float))); 
a[0]= 0; a[1]= 1; a[2]= 2; a[3]= 3; a[4]= 4; a[5]= 5; a[6]= 6; a[7]= 7; 
float* b = (float*)(malloc(8*sizeof(float))); 
setIndexedGridInfo(a,b); 

..... 

thrust::device_ptr<float> d_oldData(a); 
thrust::device_ptr<float> d_newData(b); 

thrust::device_ptr предназначен для «оборачивания» указатель на память устройства выделяемого с API CUDA, так что тяга может использовать его. Вы пытаетесь обрабатывать указатель узла непосредственно как указатель устройства. Это незаконно. Вы можете изменить свой setIndexedGridInfo функцию следующим образом:

void setIndexedGridInfo(float* a, float*b, const int n) 
{ 

    thrust::device_vector<float> d_oldData(a,a+n); 
    thrust::device_vector<float> d_newData(b,b+n); 

    float c = 0.0; 

    thrust::for_each(
     thrust::make_zip_iterator(thrust::make_tuple(d_oldData.begin(),d_newData.begin())), 
     thrust::make_zip_iterator(thrust::make_tuple(d_oldData.end(),d_newData.end())), 
     grid_functor(c)); 
} 

device_vector конструктор будет выделять память устройства, а затем скопировать содержимое памяти хоста к устройству. Это должно исправить ошибку, которую вы видите, хотя я не уверен, что вы пытаетесь сделать с итератором for_each, и правильный ли функтор, который у вас есть.


Edit:

Вот полная, компилируется, работоспособная версия коды:

#include <cstdlib> 
#include <cstdio> 
#include <thrust/device_vector.h> 
#include <thrust/for_each.h> 
#include <thrust/copy.h> 

struct grid_functor 
{ 
    float a; 

    __host__ __device__ 
    grid_functor(float grid_Info) : a(grid_Info) {} 

    template <typename Tuple> 
    __device__ 
    void operator()(Tuple t) 
    { 
     volatile float data = thrust::get<0>(t); 
     float pos = data + 0.1f; 
     thrust::get<1>(t) = pos; 
    } 

}; 

void setIndexedGridInfo(float* a, float*b, const int n) 
{ 

    thrust::device_vector<float> d_oldData(a,a+n); 
    thrust::device_vector<float> d_newData(b,b+n); 

    float c = 0.0; 

    thrust::for_each(
     thrust::make_zip_iterator(thrust::make_tuple(d_oldData.begin(),d_newData.begin())), 
     thrust::make_zip_iterator(thrust::make_tuple(d_oldData.end(),d_newData.end())), 
     grid_functor(c)); 

    thrust::copy(d_newData.begin(), d_newData.end(), b); 
} 

int main(void) 
{ 
    const int n = 8; 
    float* a= (float*)(malloc(n*sizeof(float))); 
    a[0]= 0; a[1]= 1; a[2]= 2; a[3]= 3; a[4]= 4; a[5]= 5; a[6]= 6; a[7]= 7; 
    float* b = (float*)(malloc(n*sizeof(float))); 
    setIndexedGridInfo(a,b,n); 

    for(int i=0; i<n; i++) { 
     fprintf(stdout, "%d (%f,%f)\n", i, a[i], b[i]); 
    } 

    return 0; 
} 

я могу скомпилировать и запустить этот код на OS 10.6.8 хоста с CUDA 4.1 вот так:

$ nvcc -Xptxas="-v" -arch=sm_12 -g -G thrustforeach.cu 
./thrustforeach.cu(18): Warning: Cannot tell what pointer points to, assuming global memory space 
./thrustforeach.cu(20): Warning: Cannot tell what pointer points to, assuming global memory space 
./thrustforeach.cu(18): Warning: Cannot tell what pointer points to, assuming global memory space 
./thrustforeach.cu(20): Warning: Cannot tell what pointer points to, assuming global memory space 
ptxas info : Compiling entry function '_ZN6thrust6detail7backend4cuda6detail23launch_closure_by_valueINS2_18for_each_n_closureINS_12zip_iteratorINS_5tupleINS0_15normal_iteratorINS_10device_ptrIfEEEESB_NS_9null_typeESC_SC_SC_SC_SC_SC_SC_EEEEi12grid_functorEEEEvT_' for 'sm_12' 
ptxas info : Used 14 registers, 160+0 bytes lmem, 16+16 bytes smem, 4 bytes cmem[1] 
ptxas info : Compiling entry function '_ZN6thrust6detail7backend4cuda6detail23launch_closure_by_valueINS2_18for_each_n_closureINS_12zip_iteratorINS_5tupleINS0_15normal_iteratorINS_10device_ptrIfEEEESB_NS_9null_typeESC_SC_SC_SC_SC_SC_SC_EEEEj12grid_functorEEEEvT_' for 'sm_12' 
ptxas info : Used 14 registers, 160+0 bytes lmem, 16+16 bytes smem, 4 bytes cmem[1] 

$ ./a.out 
0 (0.000000,0.100000) 
1 (1.000000,1.100000) 
2 (2.000000,2.100000) 
3 (3.000000,3.100000) 
4 (4.000000,4.100000) 
5 (5.000000,5.100000) 
6 (6.000000,6.100000) 
7 (7.000000,7.100000) 
+0

Я полностью неправильно понял концепцию тяги. Я думал, что это может также передать принимающие массивы. Я просто пытался увеличить каждый элемент на 0,1. Просто для упражнений. Спасибо за помощь. –

+0

, но это инициализация device_vector не работает. device_vector недостаточно. device_vector требует также typename Alloc: device_vector

+1

Поверьте мне, это так. Я сделал небольшую синтаксическую ошибку в моих изменениях в вашем вызове 'for_each'. Посмотрите на новую версию. Я теперь проверил с помощью компилятора, и он работает для меня с CUDA 4.1 на компьютере с вычислительным 1.2. – talonmies