| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Системное программирование и WinAPI > CUDA. Двойная точность |
| Автор: Frenky86 30.3.2009, 14:58 |
| К специалистам по CUDA вопрос о двойной точности вычисслений. Моя видиокарта не поддерживает двойной точности, поэтому пришлось её эмулировать. Так как у самого добиться существенных результатов добиться не получилось, хотелось бы попросить помощи у более опытных старших товарищей. Почитав на форуме nVidia (http://forums.nvidia.com/index.php?showtopic=73067&st=0&gopid=524302&#entry524302) как это реализуется, попытался сделать нечто подобное. Тестовый пример самый простой (возведение числа в квадрат) Моё ядро. /* Kernel */ __global__ void square_elements(float2* in, float2* out, int N) { int idx = blockIdx.x*blockDim.x+threadIdx.x; if ( idx < N) out[idx]=in[idx]*in[idx]; } Моя mex-функция (CUDA заинтересовала для расчетов больших матриц на MatLab-е) void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int i, j, m, n; double *data1, *data2; float2 *data1f, *data2f; /* on GPU */ float2 *data1f_gpu, *data2f_gpu; mxClassID category; if (nrhs != nlhs) mexErrMsgTxt("The number of input and output arguments must be the same."); for (i = 0; i < nrhs; i++) { /* Find the dimensions of the data */ m = mxGetM(prhs[i]); n = mxGetN(prhs[i]); /* Create an mxArray for the output data */ plhs[i] = mxCreateDoubleMatrix(m, n, mxREAL); /* Create an input and output data array on the GPU*/ cudaMalloc( (void **) &data1f_gpu,sizeof(float2)*m*n); cudaMalloc( (void **) &data2f_gpu,sizeof(float2)*m*n); /* Retrieve the input data */ data1 = mxGetPr(prhs[i]); /* Check if the input array is single or double precision */ category = mxGetClassID(prhs[i]); if( category == mxSINGLE_CLASS) { /* The input array is single precision, it can be sent directly to the card */ cudaMemcpy( data1f_gpu, data1, sizeof(float)*m*n, cudaMemcpyHostToDevice); } if( category == mxDOUBLE_CLASS) { /* The input array is in double precision, it needs to be converted t floats before being sent to the card */ data1f = (float2 *) mxMalloc(sizeof(float2)*m*n); for (j = 0; j < m*n; j++) { set(*data1f, *data1); } cudaMemcpy( data1f_gpu, data1f, sizeof(float)*n*m, cudaMemcpyHostToDevice); } data2f = (float2 *) mxMalloc(sizeof(float2)*m*n); /* Compute execution configuration using 128 threads per block */ dim3 dimBlock(128); dim3 dimGrid((m*n)/dimBlock.x); if ( (n*m) % 128 !=0 ) dimGrid.x+=1; /* Call function on GPU */ square_elements<<<dimGrid,dimBlock>>>(data1f_gpu, data2f_gpu, n*m); /* Copy result back to host */ cudaMemcpy( data2f, data2f_gpu, sizeof(float)*n*m, cudaMemcpyDeviceToHost); /* Create a pointer to the output data */ data2 = mxGetPr(plhs[i]); /* Convert from single to double before returning */ for (j = 0; j < m*n; j++) { data2[j] = data2f[j].x + data2f[j].y; } /* Clean-up memory on device and host */ mxFree(data1f); mxFree(data2f); cudaFree(data1f_gpu); cudaFree(data2f_gpu); } } Но вот прикол, разницы между ответом при использовании float и float2 нет почти никакой Подскажите, что я делаю неверно |
| Автор: Dem_max 30.3.2009, 15:18 |
| Используй фортран для вычислений. |
| Автор: Frenky86 31.3.2009, 07:31 |
| Всем спасибо, вопрос решен. |