はじめに
この記事では、CPUとGPUの計算能力に関する計算の並列化について簡単に説明します。 アルゴリズム自体の説明に進む前に、タスクを紹介します。
有限差分法によって問題を解決するためのシステムをシミュレートする必要があります。 数学的な観点から、これは次のとおりです。 いくつかの有限メッシュがある場合:
不明なグリッド値は、有限差分法による次の式によって検出されます。
CPUの並列化
CPUでの並列コンピューティングには、OpenMPに似た並列技術が使用されます。 並列は、並列ループと領域のサポートを提供するC#で使用される内部テクノロジーです。
並列での並列計算:
/* n*m T eps */ /* , , . , .*/ private void Parallelization(int n, int m, float[,] T, float eps) { int time; // bool flag = false; // int interetion = 0; // float epsilint; // float[,] count_eps = new float[n,m]; // float[,] T_new = new float[n, m]; // - time = Environment.TickCount; // do { epsilint = eps; Parallel.For(1, n-1, i => { Parallel.For(1, m - 1, j => { // T_new[i, j] = (T[i - 1, j] + T[i + 1, j] + T[i, j - 1] + T[i, j + 1]) / 4; // count_eps[i, j] = Math.Abs(T_new[i, j] - T[i, j]); // if (count_eps[i,j] > epsilint) { epsilint = count_eps[i,j]; } T[i, j] = T_new[i, j]; }); }); interetion++; }while(epsilint > eps || epsilint != eps); // time = Environment.TickCount - time; // Output(n, m, time, interetion, "OpenMP Parallezetion"); // }
GPU並列化
GPUでの並列コンピューティングには、CUDAテクノロジーが使用されます。 CUDAはNVIDIA並列コンピューティングアーキテクチャであり、GPUの使用によりコンピューティングパフォーマンスを大幅に向上させることができます。
CUDAでの並列コンピューティング:
/* CUDA, */ #define CUDA_DEBUG #ifdef CUDA_DEBUG #define CUDA_CHECK_ERROR(err) \ if (err != cudaSuccess) { \ printf("Cuda error: %s\n", cudaGetErrorString(err)); \ printf("Error in file: %s, line: %i\n", __FILE__, __LINE__); \ } \ #else #define CUDA_CHECK_ERROR(err) #endif /* GPU*/ __global__ void VectorAdd(float* inputMatrix, float* outputMatrix, int n, int m) { int i = threadIdx.x + blockIdx.x * blockDim.x; // int j = threadIdx.y + blockIdx.y * blockDim.y; // if(i < n -1 && i > 0) { if( j < m - 1 && j > 0) // outputMatrix[i * n + j] = (inputMatrix[(i - 1) * n + j ] + inputMatrix[(i + 1) * n + j] + inputMatrix[i * n + (j - 1)] + inputMatrix[i * n + (j + 1)])/4; } } /* n*m T eps */ /* GPU , T */ void OpenCL_Parallezetion(int n, int m, float *T, float eps) { int matrixsize = n * m; // CPU int byteSize = matrixsize * sizeof(float); // GPU time_t start, end; // float time; // float* T_new = new float[matrixsize]; // - float *cuda_T_in; // - GPU float *cuda_T_out; // - GPU CUDA_CHECK_ERROR(cudaMalloc((void**)&cuda_T_in, byteSize)); // GPU CUDA_CHECK_ERROR(cudaMalloc((void**)&cuda_T_out, byteSize)); float epsilint; // float count_eps; // int interetaion = 0; // start = clock(); // dim3 gridsize = dim3(n,m,1); // (x,y,z) GPU do{ epsilint = eps; CUDA_CHECK_ERROR(cudaMemcpy(cuda_T_in, T, byteSize, cudaMemcpyHostToDevice)); // GPU VectorAdd<<< gridsize, m >>>(cuda_T_in, cuda_T_out, n, m); CUDA_CHECK_ERROR(cudaMemcpy(T_new, cuda_T_out, byteSize, cudaMemcpyDeviceToHost)); // GPU for(int i = 1; i < n -1; i++) { for(int j = 1; j < m -1; j++) { // count_eps = T_new[i* n + j ] - T[i* n + j]; // if(count_eps > epsilint) { epsilint = count_eps; } T[i * n + j] = T_new[i * n + j]; } } interetaion++; }while(epsilint > eps || epsilint != eps);// end = clock(); // time = (end - start); // /* CPU GPU*/ free(T); free(T_new); cudaFree(cuda_T_in); cudaFree(cuda_T_out); Output(n, m, time, interetaion); // }