У меня проблема с моим первым приложением 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);
}
Большое спасибо! Я не знал, что вызов ядра был асинхронным. Добавлен cudaDeviceSynchronize сразу после вызова ядра. Через несколько секунд (что, я думаю, показывает, что он действительно что-то делает), если не удается выполнить «неуказанный сбой запуска». Я проверю код на повреждение памяти. Кстати, произойдет ли сбой ядра, если произойдет переполнение float? Или он просто проигнорирует его и продолжит с неправильным значением? –
Запускаете ли вы приложение на том же графическом процессоре, который также используется ОС для отображения пользовательского интерфейса? Обратите внимание, что эти устройства имеют «сторожевой таймер» - длительные ядра принудительно завершаются, чтобы избежать прерывистого интерфейса. Для длительных вычислений вам нужен специальный графический адаптер. – Eugene
Обратите внимание, что я вижу ошибки при работе на графическом процессоре, к которому подключен мой монитор во время работы кода на запасном графическом процессоре, не дает никаких ошибок. Я запускаю его с помощью cuda-memcheck сейчас, занимает некоторое время :) – Eugene