2012-08-08 4 views
0

У меня проблема с моим первым приложением CUDA. В основном он должен генерировать N линейных дифференциальных уравнений и решать их численно с использованием метода первого порядка. Переменная t (время) итерации от 0 до T с шагом = TAU = 0,0001. Если T достаточно мал (скажем, 0,001), все в порядке, но если T == 0,1 или больше, кажется, что ядро ​​ничего не делает. Как я могу рассмотреть эту ситуацию?Kernel останавливается без причины

N - число уравнений, TAU - шаг по времени, TN - число потоков в блоке, T - время окончания

Переменная r ничего не делает. Я использовал его для проверки того, что ядро ​​ничего не делает. Так что, если T == 0,0001 затем r == 283, но если T == 0,1, r == 0.

#include <stdio.h> 
#include <math.h> 
#include <time.h> 

#define N 4096 
#define TAU 0.0001f 
#define TN 2 
#define T 0.1f 
#define PI 3.141592f 

__global__ void kern(float* v, float* m, float* r) 
{ 
    *r = 283; 
    __syncthreads(); 
    int tid = blockIdx.x*TN + threadIdx.x; 

    for(float t = 0; t <= T; t += TAU) 
    { 
     float f = 0; 
     __syncthreads(); 
     for(int k = 0; k < N; ++k) 
      f += m[N*tid + k]*v[k]; 
     f *= TAU; 
     f += v[tid]; 
     __syncthreads(); 
     v[tid] = f; 
    } 
} 

int main() 
{ 
    float* v = new float[N]; 
    float* m = new float[N*N]; 

    for(int i = 0; i < N; ++i) 
     v[i] = sin(2*PI*i/N); //setting initial conditions 

    for(int i = 0; i < N*N; ++i) 
     m[i] = cos(2*PI*i/(N*N)); //coefficients in right hand part of the equations 

    // printing some of the values (total: 8 values) to compare with result 
    for(int i = 0; i < N*N; i += N*N/8) printf("%f ", m[i]); printf("\n\n"); 
    for(int i = 0; i < N; i += N/8) printf("%f ", v[i]); printf("\n"); 

    float* cv; 
    float* cm; 
    float* cr; 
    cudaMalloc((void**)&cv, N*sizeof(float)); 
    cudaMalloc((void**)&cm, N*N*sizeof(float)); 
    cudaMalloc((void**)&cr, sizeof(float)); 

    cudaMemcpy(cv, v, N*sizeof(float), cudaMemcpyHostToDevice); 
    cudaMemcpy(cm, m, N*N*sizeof(float), cudaMemcpyHostToDevice); 

    dim3 blocks(N/TN); 
    dim3 threads(TN); 

    time_t ts = time(0); 
    printf("starting kernel\n"); 
    kern<<<blocks, threads>>>(cv, cm, cr); 
    printf("kernel stopped\n"); 
    time_t ts_end = time(0); 

    cudaMemcpy(v, cv, N*sizeof(float), cudaMemcpyDeviceToHost); 
    float r; 
    cudaMemcpy(&r, cr, sizeof(float), cudaMemcpyDeviceToHost); 

    for(int i = 0; i < N; i += N/8) printf("%f ", v[i]); printf("\n"); 
    printf("%d\n", ts_end - ts); 
    printf("result: %f\n", r); 


    delete[] m; 
    delete[] v; 

    cudaFree(cv); 
    cudaFree(cm); 
    cudaFree(cr); 
} 

ответ

1

Что вы подразумеваете под "kernel stops"? Вы имеете в виду распечатку с строки 62?

Обратите внимание, что запуска ядра запускаются асинхронно, то есть строка 61 не ждет завершения ядра. Вы должны использовать «cudaDeviceSynchronize» после запуска ядра, чтобы дождаться завершения ядра. Обратите внимание, что cudaMemcpy также синхронизируется при запуске ядра.

+0

Большое спасибо! Я не знал, что вызов ядра был асинхронным. Добавлен cudaDeviceSynchronize сразу после вызова ядра. Через несколько секунд (что, я думаю, показывает, что он действительно что-то делает), если не удается выполнить «неуказанный сбой запуска». Я проверю код на повреждение памяти. Кстати, произойдет ли сбой ядра, если произойдет переполнение float? Или он просто проигнорирует его и продолжит с неправильным значением? –

+0

Запускаете ли вы приложение на том же графическом процессоре, который также используется ОС для отображения пользовательского интерфейса? Обратите внимание, что эти устройства имеют «сторожевой таймер» - длительные ядра принудительно завершаются, чтобы избежать прерывистого интерфейса. Для длительных вычислений вам нужен специальный графический адаптер. – Eugene

+0

Обратите внимание, что я вижу ошибки при работе на графическом процессоре, к которому подключен мой монитор во время работы кода на запасном графическом процессоре, не дает никаких ошибок. Я запускаю его с помощью cuda-memcheck сейчас, занимает некоторое время :) – Eugene

1

Всегда проверять код возврата при вызове API вызовы CUDA.

Скорее всего, ваша программа никогда не запускается из-за ошибки api.

+0

Благодарим вас за консультацию. Готово. Когда T == 0.0001 работает нормально. Когда T == 0,1 программы выходят из строя при вызове CudaSafeCall (cudaMemcpy (v, cv, N * sizeof (float), cudaMemcpyDeviceToHost)); с сообщением «неуказанный сбой запуска». В обоих случаях cudaGetLastError сразу после вызова ядра возвращает cudaSuccess, но когда T == 0,1 кажется, что ядро ​​ничего не делает. –

Смежные вопросы