追è¨(2009/12/12): ããã§ç¤ºãã¦ãã³ã¼ãã¯ããªãã²ã©ãã®ã§å°ãæç´ããã¦、CUDAã§ä½æããååååå¦è¨ç®ããã°ã©ã ãæ¸ãç´ãã¦ã¿ãã¨ããè¨äºã«ã¾ã¨ãã。ãã¡ããåç
§ãã¦æ¬²ãã。
æè¿、èªåã®å¨ãã§ã¯CUDAã使ã£ãGPGPUãæµè¡ã£ã¦ããã®ã§、ã©ããªãã®ããã®é±æ«ã«ããã£ã¦ã¿ã。
ä¸æ¥ç®ã¯NVIDIA GeForce 8800 GTSãæè¼ããWindows XPãã·ã³ã«CUDAãã¤ã³ã¹ãã¼ã«ããã¦ãªãã¡ã¬ã³ã¹ããµã³ãã«ããã°ã©ã ããã©ãã©ã¨èªãã§ã¿ã。äºæ¥ç®ã«ãªãã¡ãã£ã¦ååååå¦(MD)è¨ç®ããã°ã©ã ãæ¸ãã。æ¬ä¼¼ååãæ±ã£ã¦ãã、å ¨ååã®vdWåã¨ã¯ã¼ãã³åã®ã¿ãèæ ®ãã¦ååå çµåã«ã¤ãã¦ã¯èæ ®ããªã、液滴ä¸ã®MDè¨ç®ã 。åãæ¢ãã、åå¾20à ã®æ¶²æ»´ä¸ã«1229ååãå ¥ãã¦1000ã¹ãããè¨ç®ããã¦ã¿ã。C++ã§æ¸ããããã°ã©ã ã§ã¯4å30ç§ããã£ãè¨ç®ãCUDAã§ã¯32ç§ã§è¨ç®ã§ãã。ç´9åã»ã©ã®é度ãåºã¦ããããã 。
ã¾ã、C++ã®ã³ã¼ããä½µãã¦ä¸æ¥ã§æ¸ããã®ã§æé©åãé«éåã«ã¤ãã¦ã¯èæ ®ãã¦ããªã。å¾ã§ã¹ã¬ããã§ã®åå²ããããããããã¨æã£ã¦iã¨jããã®ã¾ã¾å ¨é¨è¨ç®ãã¦ããã。æ°ãåãããã¡ããã¨ããããã°ã©ã ãæ¸ãã¦ã¿ããã。
CUDAã¢ã¼ããã¯ãã£ã«ã¤ãã¦ã¯ã¾ã ã¾ã ç解ã足ããªã。å¹çã®ããã¡ã¢ãªã®æ±ãæ¹ãè¦ããªãã¨ãªã。ãã¨、sharedã¡ã¢ãªããã¾ãæ±ãã¦ãªãã£ã½ã。ãããã«ä¸æ¥äºæ¥ããããã¤ã。
åå¿è ãä¸æ¥ã§æ¸ããã³ã¼ããªã®ã§åèã«ãªããããããªãã、以ä¸ã«ã½ã¼ã¹ã³ã¼ãã¨ãµã³ãã«ã®å ¥åãã¼ã¿ã示ãã¦ãã。å ¥åãã¼ã¿ã«ã¤ãã¦ã¯、ä¸è¨ã§ç¨ãã1229ååã§ã¯ããã°è¨äºããã«ã¯å¤§ããããã®ã§154ååã®å°ããªãã¼ã¿ãç¨æãã。ã¾ã、è¨äºã®è¡¨ç¤ºéãå¤ããªããããã®ã§C++ã®ã½ã¼ã¹ã¯å²æããã¦ããã£ã。Windowsä¸ã§ã®ã³ã³ãã¤ã«ã¯ä¸è¨ã®éã。
nvcc -lcutil32 -lkernel32 --host-compilation c++ -Xcompiler /EHsc,/W3,/nologo,/O2,/Zi,/MT simple_md_gpu.cu -o simple_md_gpu.exe
å ¥åãã¡ã¤ã«ãmd.datã¨ãã¦、100ã¹ãããè¨ç®ãããå ´åã¯、以ä¸ã®ããã«å®è¡ãã。
simple_md_gpu md.dat 100
æåã«åææ§é ã表示ãã、次ãã§ã¹ããããã¨ã®ã¨ãã«ã®ã¼、æå¾ã«æçµæ§é ãåºåããã。
simple_md_gpu.cu
//////////////////////////////////////////////////////////////// // Simple Molecular Dynamics using GPU by nox, 2009.03.22. // // Perform molecular dynamics for pseudo-atoms without internal // interactions, such as bonds, angles, dihedrals. Only vdW and // Coulomb interactions. #include <iostream> #include <iomanip> #include <fstream> #include <sstream> #include <cmath> #include <cutil_inline.h> using namespace std; const int BLOCK = 256; const int WIDTH = 2048; __device__ float Distance(float* crd, int i, int j) { float dx = crd[i * 3] - crd[j * 3]; float dy = crd[i * 3 + 1] - crd[j * 3 + 1]; float dz = crd[i * 3 + 2] - crd[j * 3 + 2]; return sqrtf(dx * dx + dy * dy + dz * dz); } __device__ float Energy(float* ene, int num_atoms) { float sum = 0.0f; for (int i = 0; i < num_atoms; i++) sum += ene[i]; return sum / 2.0f; } __global__ void Center(float* crd,int num_atoms) { __shared__ float d[3]; for (int i = 0; i < 3; i++) d[i] = 0.0f; for (int i = 0; i < num_atoms; i++) for (int j = 0; j < 3; j++) d[j] += crd[i * 3 + j]; for (int i = 0; i < 3; i++) d[i] /= num_atoms; for (int i = 0; i < num_atoms; i++) for (int j = 0; j < 3; j++) crd[i * 3 + j] -= d[j]; } // Calculate energies and forces // Energy = vdW + Coulomb // vdW // U = eps * [(Rij / r[i])^12 - 2 * (Rij / r[i])^6] // F = -12 * eps / Rij * [(Rij / r[i])^13 - (Rij / r[i])^7] * r_xyz / r[i] // Coulomb // U = SUM_i>j qiqj / r[i] // F = SUM_j qiqj / r[i]^3 * r_xyz __global__ void Calc(float* crd, float* f, float* ene, float* chg, int num_atoms, float* tene) { int dtx = blockIdx.x * blockDim.x + threadIdx.x; const float eps = 0.2f; const float Rij = 2.5f; float r, r_xyz, df, r12, r6, q; for (int i = dtx; i < num_atoms; i += WIDTH) ene[i] = 0.0f; __syncthreads(); for (int i = dtx; i < num_atoms; i += WIDTH) { for (int j = 0; j < num_atoms; j++) { if (i == j) continue; r = Distance(crd, i, j); q = chg[i] * chg[j]; r12 = powf(Rij / r, 12); r6 = powf(Rij / r, 6); ene[i] += eps * (r12 - 2.0f * r6) + q / r; for (int k = 0; k < 3; k++) { r_xyz = crd[i * 3 + k] - crd[j * 3 + k]; df = (12 * eps / Rij) * (r12 * Rij / r - r6 * Rij / r) * r_xyz / r; df += q / powf(r, 3) * r_xyz; f[i * 3 + k] += df; } } } __syncthreads(); *tene = Energy(ene, num_atoms); } __global__ void Move(float* crd, float* f, int num_atoms, float cap_range) { int dtx = blockIdx.x * blockDim.x + threadIdx.x; float r, dr; for (int i = dtx; i < num_atoms; i += WIDTH) { for (int j = 0; j < 3; j++) { crd[i * 3 + j] += f[i * 3 + j] * 0.01f; f[i * 3 + j] = 0.0f; } r = 0.0f; for (int j = 0; j < 3; j++) r += crd[i * 3 + j] * crd[i * 3 + j]; dr = r - cap_range * cap_range; if (dr > 0.0f) for (int j = 0; j < 3; j++) f[i * 3 + j] -= crd[i * 3 + j] / cap_range * dr * 0.01f; } } class SimpleMD { private: int num_steps; int num_atoms; float cap_range; float *h_crd, *h_f, *h_ene, *h_chg; float *d_crd, *d_f, *d_ene, *d_chg; float tene; public: SimpleMD(int n, char*); ~SimpleMD(); void ReadCrd(char*); void PrintCrd(); void Run(); }; SimpleMD::SimpleMD(int n, char* fname) : num_steps(n) { ReadCrd(fname); h_f = new float[num_atoms * 3]; h_ene = new float[num_atoms]; for (int i = 0; i < num_atoms; i++) { for (int j = 0; j < 3; j++) h_f[i * 3 + j] = 0.0f; h_ene[i] = 0.0f; } cudaMalloc((void**)&d_crd, sizeof(float) * num_atoms * 3); cudaMalloc((void**)&d_f, sizeof(float) * num_atoms * 3); cudaMalloc((void**)&d_ene, sizeof(float) * num_atoms); cudaMalloc((void**)&d_chg, sizeof(float) * num_atoms); } SimpleMD::~SimpleMD() { cudaFree(d_chg); cudaFree(d_ene); cudaFree(d_f); cudaFree(d_crd); delete[] h_ene; delete[] h_f; delete[] h_chg; delete[] h_crd; } void SimpleMD::ReadCrd(char* fname) { fstream fs(fname, ios_base::in); string line; stringstream ss; if (!fs.is_open()) { cerr << "File open error: " << fname << endl; exit(1); } getline(fs, line); cout << line << endl; getline(fs, line); ss.str(line); ss >> num_atoms; ss.clear(); getline(fs, line); ss.str(line); ss >> cap_range; ss.clear(); h_crd = new float[num_atoms * 3]; h_chg = new float[num_atoms]; for (int i = 0; i < num_atoms; i++) { getline(fs, line); ss.str(line); ss >> h_crd[i * 3] >> h_crd[i * 3 + 1] >> h_crd[i * 3 + 2] >> h_chg[i]; ss.clear(); ss.str(""); } fs.close(); } void SimpleMD::PrintCrd() { cout << endl; cout << num_atoms << endl; cout << cap_range << endl; for (int i = 0; i < num_atoms; i++) { for (int j = 0; j < 3; j++) cout << " " << fixed << setw(10) << setprecision(6) << h_crd[i * 3 + j]; cout << " " << fixed << setw(8) << setprecision(4) << h_chg[i]; cout << endl; } } void SimpleMD::Run() { float *d_tene; cudaMalloc((void**)&d_tene, sizeof(float)); cudaMemcpy(d_crd, h_crd, sizeof(float) * num_atoms * 3, cudaMemcpyHostToDevice); cudaMemcpy(d_f, h_f, sizeof(float) * num_atoms * 3, cudaMemcpyHostToDevice); cudaMemcpy(d_ene, h_ene, sizeof(float) * num_atoms, cudaMemcpyHostToDevice); cudaMemcpy(d_chg, h_chg, sizeof(float) * num_atoms, cudaMemcpyHostToDevice); dim3 grid(WIDTH / BLOCK, 1, 1); dim3 threads(BLOCK, 1, 1); Center<<<1, 1>>>(d_crd, num_atoms); for (int i = 0; i < num_steps; i++) { Calc<<<grid, threads>>>(d_crd, d_f, d_ene, d_chg, num_atoms, d_tene); Move<<<grid, threads>>>(d_crd, d_f, num_atoms, cap_range); Center<<<1, 1>>>(d_crd, num_atoms); cudaMemcpy(&tene, d_tene, sizeof(float), cudaMemcpyDeviceToHost); cout << "Energy (" << setw(7) << i + 1 << "): "; cout << fixed << setw(15) << setprecision(5) << tene << endl; } cudaMemcpy(h_crd, d_crd, sizeof(float) * num_atoms * 3, cudaMemcpyDeviceToHost); cudaMemcpy(h_f, d_f, sizeof(float) * num_atoms * 3, cudaMemcpyDeviceToHost); cudaMemcpy(h_ene, d_ene, sizeof(float) * num_atoms, cudaMemcpyDeviceToHost); cudaFree(d_tene); } int main(int argc, char** argv) { if (argc != 3) { cerr << "Usage: " << argv[0] << " input_file number_of_steps" << endl; cerr << "Input: line 1 : title" << endl; cerr << " line 2 : number of atoms" << endl; cerr << " line 3 : radius of droplet" << endl; cerr << " line 4-: x-crd y-crd z-crd charge" << endl; exit(1); } stringstream ss; int nstep; cutilDeviceInit(1, argv); ss.str(argv[2]); ss >> nstep; SimpleMD md(nstep, argv[1]); md.PrintCrd(); md.Run(); md.PrintCrd(); return 0; }
ãµã³ãã«å ¥åãã¡ã¤ã«: md.dat
simple_md_gpu sample data 154 10.0 -7.00000 -7.00000 -1.00000 -1.000 -7.00000 -4.00000 -4.00000 1.000 -7.00000 -4.00000 -1.00000 -1.000 -7.00000 -4.00000 2.00000 1.000 -7.00000 -4.00000 5.00000 -1.000 -7.00000 -1.00000 -7.00000 1.000 -7.00000 -1.00000 -4.00000 -1.000 -7.00000 -1.00000 -1.00000 1.000 -7.00000 -1.00000 2.00000 -1.000 -7.00000 -1.00000 5.00000 1.000 -7.00000 2.00000 -4.00000 -1.000 -7.00000 2.00000 -1.00000 1.000 -7.00000 2.00000 2.00000 -1.000 -7.00000 2.00000 5.00000 1.000 -7.00000 5.00000 -4.00000 -1.000 -7.00000 5.00000 -1.00000 1.000 -7.00000 5.00000 2.00000 -1.000 -7.00000 5.00000 5.00000 1.000 -4.00000 -7.00000 -4.00000 -1.000 -4.00000 -7.00000 -1.00000 1.000 -4.00000 -7.00000 2.00000 -1.000 -4.00000 -7.00000 5.00000 1.000 -4.00000 -4.00000 -7.00000 -1.000 -4.00000 -4.00000 -4.00000 1.000 -4.00000 -4.00000 -1.00000 -1.000 -4.00000 -4.00000 2.00000 1.000 -4.00000 -4.00000 5.00000 -1.000 -4.00000 -4.00000 8.00000 1.000 -4.00000 -1.00000 -7.00000 -1.000 -4.00000 -1.00000 -4.00000 1.000 -4.00000 -1.00000 -1.00000 -1.000 -4.00000 -1.00000 2.00000 1.000 -4.00000 -1.00000 5.00000 -1.000 -4.00000 -1.00000 8.00000 1.000 -4.00000 2.00000 -7.00000 -1.000 -4.00000 2.00000 -4.00000 1.000 -4.00000 2.00000 -1.00000 -1.000 -4.00000 2.00000 2.00000 1.000 -4.00000 2.00000 5.00000 -1.000 -4.00000 2.00000 8.00000 1.000 -4.00000 5.00000 -7.00000 -1.000 -4.00000 5.00000 -4.00000 1.000 -4.00000 5.00000 -1.00000 -1.000 -4.00000 5.00000 2.00000 1.000 -4.00000 5.00000 5.00000 -1.000 -4.00000 8.00000 -4.00000 1.000 -4.00000 8.00000 -1.00000 -1.000 -4.00000 8.00000 2.00000 1.000 -1.00000 -7.00000 -7.00000 -1.000 -1.00000 -7.00000 -4.00000 1.000 -1.00000 -7.00000 -1.00000 -1.000 -1.00000 -7.00000 2.00000 1.000 -1.00000 -7.00000 5.00000 -1.000 -1.00000 -4.00000 -7.00000 1.000 -1.00000 -4.00000 -4.00000 -1.000 -1.00000 -4.00000 -1.00000 1.000 -1.00000 -4.00000 2.00000 -1.000 -1.00000 -4.00000 5.00000 1.000 -1.00000 -4.00000 8.00000 -1.000 -1.00000 -1.00000 -7.00000 1.000 -1.00000 -1.00000 -4.00000 -1.000 -1.00000 -1.00000 -1.00000 1.000 -1.00000 -1.00000 2.00000 -1.000 -1.00000 -1.00000 5.00000 1.000 -1.00000 -1.00000 8.00000 -1.000 -1.00000 2.00000 -7.00000 1.000 -1.00000 2.00000 -4.00000 -1.000 -1.00000 2.00000 -1.00000 1.000 -1.00000 2.00000 2.00000 -1.000 -1.00000 2.00000 5.00000 1.000 -1.00000 2.00000 8.00000 -1.000 -1.00000 5.00000 -7.00000 1.000 -1.00000 5.00000 -4.00000 -1.000 -1.00000 5.00000 -1.00000 1.000 -1.00000 5.00000 2.00000 -1.000 -1.00000 5.00000 5.00000 1.000 -1.00000 5.00000 8.00000 -1.000 -1.00000 8.00000 -4.00000 1.000 -1.00000 8.00000 -1.00000 -1.000 -1.00000 8.00000 2.00000 1.000 -1.00000 8.00000 5.00000 -1.000 2.00000 -7.00000 -4.00000 1.000 2.00000 -7.00000 -1.00000 -1.000 2.00000 -7.00000 2.00000 1.000 2.00000 -7.00000 5.00000 -1.000 2.00000 -4.00000 -7.00000 1.000 2.00000 -4.00000 -4.00000 -1.000 2.00000 -4.00000 -1.00000 1.000 2.00000 -4.00000 2.00000 -1.000 2.00000 -4.00000 5.00000 1.000 2.00000 -4.00000 8.00000 -1.000 2.00000 -1.00000 -7.00000 1.000 2.00000 -1.00000 -4.00000 -1.000 2.00000 -1.00000 -1.00000 1.000 2.00000 -1.00000 2.00000 -1.000 2.00000 -1.00000 5.00000 1.000 2.00000 -1.00000 8.00000 -1.000 2.00000 2.00000 -7.00000 1.000 2.00000 2.00000 -4.00000 -1.000 2.00000 2.00000 -1.00000 1.000 2.00000 2.00000 2.00000 -1.000 2.00000 2.00000 5.00000 1.000 2.00000 2.00000 8.00000 -1.000 2.00000 5.00000 -7.00000 1.000 2.00000 5.00000 -4.00000 -1.000 2.00000 5.00000 -1.00000 1.000 2.00000 5.00000 2.00000 -1.000 2.00000 5.00000 5.00000 1.000 2.00000 5.00000 8.00000 -1.000 2.00000 8.00000 -4.00000 1.000 2.00000 8.00000 -1.00000 -1.000 2.00000 8.00000 2.00000 1.000 2.00000 8.00000 5.00000 -1.000 5.00000 -7.00000 -4.00000 1.000 5.00000 -7.00000 -1.00000 -1.000 5.00000 -7.00000 2.00000 1.000 5.00000 -7.00000 5.00000 -1.000 5.00000 -4.00000 -7.00000 1.000 5.00000 -4.00000 -4.00000 -1.000 5.00000 -4.00000 -1.00000 1.000 5.00000 -4.00000 2.00000 -1.000 5.00000 -4.00000 5.00000 1.000 5.00000 -1.00000 -7.00000 -1.000 5.00000 -1.00000 -4.00000 1.000 5.00000 -1.00000 -1.00000 -1.000 5.00000 -1.00000 2.00000 1.000 5.00000 -1.00000 5.00000 -1.000 5.00000 -1.00000 8.00000 1.000 5.00000 2.00000 -7.00000 -1.000 5.00000 2.00000 -4.00000 1.000 5.00000 2.00000 -1.00000 -1.000 5.00000 2.00000 2.00000 1.000 5.00000 2.00000 5.00000 -1.000 5.00000 2.00000 8.00000 1.000 5.00000 5.00000 -7.00000 -1.000 5.00000 5.00000 -4.00000 1.000 5.00000 5.00000 -1.00000 -1.000 5.00000 5.00000 2.00000 1.000 5.00000 5.00000 5.00000 -1.000 5.00000 8.00000 -1.00000 1.000 5.00000 8.00000 2.00000 -1.000 8.00000 -4.00000 -4.00000 1.000 8.00000 -4.00000 -1.00000 -1.000 8.00000 -4.00000 2.00000 1.000 8.00000 -1.00000 -4.00000 -1.000 8.00000 -1.00000 -1.00000 1.000 8.00000 -1.00000 2.00000 -1.000 8.00000 -1.00000 5.00000 1.000 8.00000 2.00000 -4.00000 -1.000 8.00000 2.00000 -1.00000 1.000 8.00000 2.00000 2.00000 -1.000 8.00000 2.00000 5.00000 1.000 8.00000 5.00000 -1.00000 -1.000 8.00000 5.00000 2.00000 1.000
追è¨:
ç¹ã«è¨è¿°ããªãã£ãã、åºåã¨ãã«ã®ã¼ã¯ããã³ã·ã£ã«ã¨ãã«ã®ã¼ãªã®ã§、念ã®ãã。ã¾ã、ããã§ã¯æéç©åã«ã¤ãã¦èæ ®ãã¦ããªã。NVEã¢ã³ãµã³ãã«(å®ã¨ãã«ã®ã¼)ã§ããã°、æéç©åã¯é度ãã«ã¬æ³ããã£ã¨ãå®è£ ããããããã«æã。dt/2ã§é度ãæ±ã、ããããdtã®åº§æ¨ãè¨ç®ã、ãã®åº§æ¨ããããã«dt/2ã§é度ãæ±ãã。
æè¿、èªåã®å¨ãã§ã¯CUDAã使ã£ãGPGPUãæµè¡ã£ã¦ããã®ã§、ã©ããªãã®ããã®é±æ«ã«ããã£ã¦ã¿ã。
ä¸æ¥ç®ã¯NVIDIA GeForce 8800 GTSãæè¼ããWindows XPãã·ã³ã«CUDAãã¤ã³ã¹ãã¼ã«ããã¦ãªãã¡ã¬ã³ã¹ããµã³ãã«ããã°ã©ã ããã©ãã©ã¨èªãã§ã¿ã。äºæ¥ç®ã«ãªãã¡ãã£ã¦ååååå¦(MD)è¨ç®ããã°ã©ã ãæ¸ãã。æ¬ä¼¼ååãæ±ã£ã¦ãã、å ¨ååã®vdWåã¨ã¯ã¼ãã³åã®ã¿ãèæ ®ãã¦ååå çµåã«ã¤ãã¦ã¯èæ ®ããªã、液滴ä¸ã®MDè¨ç®ã 。åãæ¢ãã、åå¾20à ã®æ¶²æ»´ä¸ã«1229ååãå ¥ãã¦1000ã¹ãããè¨ç®ããã¦ã¿ã。C++ã§æ¸ããããã°ã©ã ã§ã¯4å30ç§ããã£ãè¨ç®ãCUDAã§ã¯32ç§ã§è¨ç®ã§ãã。ç´9åã»ã©ã®é度ãåºã¦ããããã 。
ã¾ã、C++ã®ã³ã¼ããä½µãã¦ä¸æ¥ã§æ¸ããã®ã§æé©åãé«éåã«ã¤ãã¦ã¯èæ ®ãã¦ããªã。å¾ã§ã¹ã¬ããã§ã®åå²ããããããããã¨æã£ã¦iã¨jããã®ã¾ã¾å ¨é¨è¨ç®ãã¦ããã。æ°ãåãããã¡ããã¨ããããã°ã©ã ãæ¸ãã¦ã¿ããã。
CUDAã¢ã¼ããã¯ãã£ã«ã¤ãã¦ã¯ã¾ã ã¾ã ç解ã足ããªã。å¹çã®ããã¡ã¢ãªã®æ±ãæ¹ãè¦ããªãã¨ãªã。ãã¨、sharedã¡ã¢ãªããã¾ãæ±ãã¦ãªãã£ã½ã。ãããã«ä¸æ¥äºæ¥ããããã¤ã。
åå¿è ãä¸æ¥ã§æ¸ããã³ã¼ããªã®ã§åèã«ãªããããããªãã、以ä¸ã«ã½ã¼ã¹ã³ã¼ãã¨ãµã³ãã«ã®å ¥åãã¼ã¿ã示ãã¦ãã。å ¥åãã¼ã¿ã«ã¤ãã¦ã¯、ä¸è¨ã§ç¨ãã1229ååã§ã¯ããã°è¨äºããã«ã¯å¤§ããããã®ã§154ååã®å°ããªãã¼ã¿ãç¨æãã。ã¾ã、è¨äºã®è¡¨ç¤ºéãå¤ããªããããã®ã§C++ã®ã½ã¼ã¹ã¯å²æããã¦ããã£ã。Windowsä¸ã§ã®ã³ã³ãã¤ã«ã¯ä¸è¨ã®éã。
nvcc -lcutil32 -lkernel32 --host-compilation c++ -Xcompiler /EHsc,/W3,/nologo,/O2,/Zi,/MT simple_md_gpu.cu -o simple_md_gpu.exe
å ¥åãã¡ã¤ã«ãmd.datã¨ãã¦、100ã¹ãããè¨ç®ãããå ´åã¯、以ä¸ã®ããã«å®è¡ãã。
simple_md_gpu md.dat 100
æåã«åææ§é ã表示ãã、次ãã§ã¹ããããã¨ã®ã¨ãã«ã®ã¼、æå¾ã«æçµæ§é ãåºåããã。
simple_md_gpu.cu
//////////////////////////////////////////////////////////////// // Simple Molecular Dynamics using GPU by nox, 2009.03.22. // // Perform molecular dynamics for pseudo-atoms without internal // interactions, such as bonds, angles, dihedrals. Only vdW and // Coulomb interactions. #include <iostream> #include <iomanip> #include <fstream> #include <sstream> #include <cmath> #include <cutil_inline.h> using namespace std; const int BLOCK = 256; const int WIDTH = 2048; __device__ float Distance(float* crd, int i, int j) { float dx = crd[i * 3] - crd[j * 3]; float dy = crd[i * 3 + 1] - crd[j * 3 + 1]; float dz = crd[i * 3 + 2] - crd[j * 3 + 2]; return sqrtf(dx * dx + dy * dy + dz * dz); } __device__ float Energy(float* ene, int num_atoms) { float sum = 0.0f; for (int i = 0; i < num_atoms; i++) sum += ene[i]; return sum / 2.0f; } __global__ void Center(float* crd,int num_atoms) { __shared__ float d[3]; for (int i = 0; i < 3; i++) d[i] = 0.0f; for (int i = 0; i < num_atoms; i++) for (int j = 0; j < 3; j++) d[j] += crd[i * 3 + j]; for (int i = 0; i < 3; i++) d[i] /= num_atoms; for (int i = 0; i < num_atoms; i++) for (int j = 0; j < 3; j++) crd[i * 3 + j] -= d[j]; } // Calculate energies and forces // Energy = vdW + Coulomb // vdW // U = eps * [(Rij / r[i])^12 - 2 * (Rij / r[i])^6] // F = -12 * eps / Rij * [(Rij / r[i])^13 - (Rij / r[i])^7] * r_xyz / r[i] // Coulomb // U = SUM_i>j qiqj / r[i] // F = SUM_j qiqj / r[i]^3 * r_xyz __global__ void Calc(float* crd, float* f, float* ene, float* chg, int num_atoms, float* tene) { int dtx = blockIdx.x * blockDim.x + threadIdx.x; const float eps = 0.2f; const float Rij = 2.5f; float r, r_xyz, df, r12, r6, q; for (int i = dtx; i < num_atoms; i += WIDTH) ene[i] = 0.0f; __syncthreads(); for (int i = dtx; i < num_atoms; i += WIDTH) { for (int j = 0; j < num_atoms; j++) { if (i == j) continue; r = Distance(crd, i, j); q = chg[i] * chg[j]; r12 = powf(Rij / r, 12); r6 = powf(Rij / r, 6); ene[i] += eps * (r12 - 2.0f * r6) + q / r; for (int k = 0; k < 3; k++) { r_xyz = crd[i * 3 + k] - crd[j * 3 + k]; df = (12 * eps / Rij) * (r12 * Rij / r - r6 * Rij / r) * r_xyz / r; df += q / powf(r, 3) * r_xyz; f[i * 3 + k] += df; } } } __syncthreads(); *tene = Energy(ene, num_atoms); } __global__ void Move(float* crd, float* f, int num_atoms, float cap_range) { int dtx = blockIdx.x * blockDim.x + threadIdx.x; float r, dr; for (int i = dtx; i < num_atoms; i += WIDTH) { for (int j = 0; j < 3; j++) { crd[i * 3 + j] += f[i * 3 + j] * 0.01f; f[i * 3 + j] = 0.0f; } r = 0.0f; for (int j = 0; j < 3; j++) r += crd[i * 3 + j] * crd[i * 3 + j]; dr = r - cap_range * cap_range; if (dr > 0.0f) for (int j = 0; j < 3; j++) f[i * 3 + j] -= crd[i * 3 + j] / cap_range * dr * 0.01f; } } class SimpleMD { private: int num_steps; int num_atoms; float cap_range; float *h_crd, *h_f, *h_ene, *h_chg; float *d_crd, *d_f, *d_ene, *d_chg; float tene; public: SimpleMD(int n, char*); ~SimpleMD(); void ReadCrd(char*); void PrintCrd(); void Run(); }; SimpleMD::SimpleMD(int n, char* fname) : num_steps(n) { ReadCrd(fname); h_f = new float[num_atoms * 3]; h_ene = new float[num_atoms]; for (int i = 0; i < num_atoms; i++) { for (int j = 0; j < 3; j++) h_f[i * 3 + j] = 0.0f; h_ene[i] = 0.0f; } cudaMalloc((void**)&d_crd, sizeof(float) * num_atoms * 3); cudaMalloc((void**)&d_f, sizeof(float) * num_atoms * 3); cudaMalloc((void**)&d_ene, sizeof(float) * num_atoms); cudaMalloc((void**)&d_chg, sizeof(float) * num_atoms); } SimpleMD::~SimpleMD() { cudaFree(d_chg); cudaFree(d_ene); cudaFree(d_f); cudaFree(d_crd); delete[] h_ene; delete[] h_f; delete[] h_chg; delete[] h_crd; } void SimpleMD::ReadCrd(char* fname) { fstream fs(fname, ios_base::in); string line; stringstream ss; if (!fs.is_open()) { cerr << "File open error: " << fname << endl; exit(1); } getline(fs, line); cout << line << endl; getline(fs, line); ss.str(line); ss >> num_atoms; ss.clear(); getline(fs, line); ss.str(line); ss >> cap_range; ss.clear(); h_crd = new float[num_atoms * 3]; h_chg = new float[num_atoms]; for (int i = 0; i < num_atoms; i++) { getline(fs, line); ss.str(line); ss >> h_crd[i * 3] >> h_crd[i * 3 + 1] >> h_crd[i * 3 + 2] >> h_chg[i]; ss.clear(); ss.str(""); } fs.close(); } void SimpleMD::PrintCrd() { cout << endl; cout << num_atoms << endl; cout << cap_range << endl; for (int i = 0; i < num_atoms; i++) { for (int j = 0; j < 3; j++) cout << " " << fixed << setw(10) << setprecision(6) << h_crd[i * 3 + j]; cout << " " << fixed << setw(8) << setprecision(4) << h_chg[i]; cout << endl; } } void SimpleMD::Run() { float *d_tene; cudaMalloc((void**)&d_tene, sizeof(float)); cudaMemcpy(d_crd, h_crd, sizeof(float) * num_atoms * 3, cudaMemcpyHostToDevice); cudaMemcpy(d_f, h_f, sizeof(float) * num_atoms * 3, cudaMemcpyHostToDevice); cudaMemcpy(d_ene, h_ene, sizeof(float) * num_atoms, cudaMemcpyHostToDevice); cudaMemcpy(d_chg, h_chg, sizeof(float) * num_atoms, cudaMemcpyHostToDevice); dim3 grid(WIDTH / BLOCK, 1, 1); dim3 threads(BLOCK, 1, 1); Center<<<1, 1>>>(d_crd, num_atoms); for (int i = 0; i < num_steps; i++) { Calc<<<grid, threads>>>(d_crd, d_f, d_ene, d_chg, num_atoms, d_tene); Move<<<grid, threads>>>(d_crd, d_f, num_atoms, cap_range); Center<<<1, 1>>>(d_crd, num_atoms); cudaMemcpy(&tene, d_tene, sizeof(float), cudaMemcpyDeviceToHost); cout << "Energy (" << setw(7) << i + 1 << "): "; cout << fixed << setw(15) << setprecision(5) << tene << endl; } cudaMemcpy(h_crd, d_crd, sizeof(float) * num_atoms * 3, cudaMemcpyDeviceToHost); cudaMemcpy(h_f, d_f, sizeof(float) * num_atoms * 3, cudaMemcpyDeviceToHost); cudaMemcpy(h_ene, d_ene, sizeof(float) * num_atoms, cudaMemcpyDeviceToHost); cudaFree(d_tene); } int main(int argc, char** argv) { if (argc != 3) { cerr << "Usage: " << argv[0] << " input_file number_of_steps" << endl; cerr << "Input: line 1 : title" << endl; cerr << " line 2 : number of atoms" << endl; cerr << " line 3 : radius of droplet" << endl; cerr << " line 4-: x-crd y-crd z-crd charge" << endl; exit(1); } stringstream ss; int nstep; cutilDeviceInit(1, argv); ss.str(argv[2]); ss >> nstep; SimpleMD md(nstep, argv[1]); md.PrintCrd(); md.Run(); md.PrintCrd(); return 0; }
ãµã³ãã«å ¥åãã¡ã¤ã«: md.dat
simple_md_gpu sample data 154 10.0 -7.00000 -7.00000 -1.00000 -1.000 -7.00000 -4.00000 -4.00000 1.000 -7.00000 -4.00000 -1.00000 -1.000 -7.00000 -4.00000 2.00000 1.000 -7.00000 -4.00000 5.00000 -1.000 -7.00000 -1.00000 -7.00000 1.000 -7.00000 -1.00000 -4.00000 -1.000 -7.00000 -1.00000 -1.00000 1.000 -7.00000 -1.00000 2.00000 -1.000 -7.00000 -1.00000 5.00000 1.000 -7.00000 2.00000 -4.00000 -1.000 -7.00000 2.00000 -1.00000 1.000 -7.00000 2.00000 2.00000 -1.000 -7.00000 2.00000 5.00000 1.000 -7.00000 5.00000 -4.00000 -1.000 -7.00000 5.00000 -1.00000 1.000 -7.00000 5.00000 2.00000 -1.000 -7.00000 5.00000 5.00000 1.000 -4.00000 -7.00000 -4.00000 -1.000 -4.00000 -7.00000 -1.00000 1.000 -4.00000 -7.00000 2.00000 -1.000 -4.00000 -7.00000 5.00000 1.000 -4.00000 -4.00000 -7.00000 -1.000 -4.00000 -4.00000 -4.00000 1.000 -4.00000 -4.00000 -1.00000 -1.000 -4.00000 -4.00000 2.00000 1.000 -4.00000 -4.00000 5.00000 -1.000 -4.00000 -4.00000 8.00000 1.000 -4.00000 -1.00000 -7.00000 -1.000 -4.00000 -1.00000 -4.00000 1.000 -4.00000 -1.00000 -1.00000 -1.000 -4.00000 -1.00000 2.00000 1.000 -4.00000 -1.00000 5.00000 -1.000 -4.00000 -1.00000 8.00000 1.000 -4.00000 2.00000 -7.00000 -1.000 -4.00000 2.00000 -4.00000 1.000 -4.00000 2.00000 -1.00000 -1.000 -4.00000 2.00000 2.00000 1.000 -4.00000 2.00000 5.00000 -1.000 -4.00000 2.00000 8.00000 1.000 -4.00000 5.00000 -7.00000 -1.000 -4.00000 5.00000 -4.00000 1.000 -4.00000 5.00000 -1.00000 -1.000 -4.00000 5.00000 2.00000 1.000 -4.00000 5.00000 5.00000 -1.000 -4.00000 8.00000 -4.00000 1.000 -4.00000 8.00000 -1.00000 -1.000 -4.00000 8.00000 2.00000 1.000 -1.00000 -7.00000 -7.00000 -1.000 -1.00000 -7.00000 -4.00000 1.000 -1.00000 -7.00000 -1.00000 -1.000 -1.00000 -7.00000 2.00000 1.000 -1.00000 -7.00000 5.00000 -1.000 -1.00000 -4.00000 -7.00000 1.000 -1.00000 -4.00000 -4.00000 -1.000 -1.00000 -4.00000 -1.00000 1.000 -1.00000 -4.00000 2.00000 -1.000 -1.00000 -4.00000 5.00000 1.000 -1.00000 -4.00000 8.00000 -1.000 -1.00000 -1.00000 -7.00000 1.000 -1.00000 -1.00000 -4.00000 -1.000 -1.00000 -1.00000 -1.00000 1.000 -1.00000 -1.00000 2.00000 -1.000 -1.00000 -1.00000 5.00000 1.000 -1.00000 -1.00000 8.00000 -1.000 -1.00000 2.00000 -7.00000 1.000 -1.00000 2.00000 -4.00000 -1.000 -1.00000 2.00000 -1.00000 1.000 -1.00000 2.00000 2.00000 -1.000 -1.00000 2.00000 5.00000 1.000 -1.00000 2.00000 8.00000 -1.000 -1.00000 5.00000 -7.00000 1.000 -1.00000 5.00000 -4.00000 -1.000 -1.00000 5.00000 -1.00000 1.000 -1.00000 5.00000 2.00000 -1.000 -1.00000 5.00000 5.00000 1.000 -1.00000 5.00000 8.00000 -1.000 -1.00000 8.00000 -4.00000 1.000 -1.00000 8.00000 -1.00000 -1.000 -1.00000 8.00000 2.00000 1.000 -1.00000 8.00000 5.00000 -1.000 2.00000 -7.00000 -4.00000 1.000 2.00000 -7.00000 -1.00000 -1.000 2.00000 -7.00000 2.00000 1.000 2.00000 -7.00000 5.00000 -1.000 2.00000 -4.00000 -7.00000 1.000 2.00000 -4.00000 -4.00000 -1.000 2.00000 -4.00000 -1.00000 1.000 2.00000 -4.00000 2.00000 -1.000 2.00000 -4.00000 5.00000 1.000 2.00000 -4.00000 8.00000 -1.000 2.00000 -1.00000 -7.00000 1.000 2.00000 -1.00000 -4.00000 -1.000 2.00000 -1.00000 -1.00000 1.000 2.00000 -1.00000 2.00000 -1.000 2.00000 -1.00000 5.00000 1.000 2.00000 -1.00000 8.00000 -1.000 2.00000 2.00000 -7.00000 1.000 2.00000 2.00000 -4.00000 -1.000 2.00000 2.00000 -1.00000 1.000 2.00000 2.00000 2.00000 -1.000 2.00000 2.00000 5.00000 1.000 2.00000 2.00000 8.00000 -1.000 2.00000 5.00000 -7.00000 1.000 2.00000 5.00000 -4.00000 -1.000 2.00000 5.00000 -1.00000 1.000 2.00000 5.00000 2.00000 -1.000 2.00000 5.00000 5.00000 1.000 2.00000 5.00000 8.00000 -1.000 2.00000 8.00000 -4.00000 1.000 2.00000 8.00000 -1.00000 -1.000 2.00000 8.00000 2.00000 1.000 2.00000 8.00000 5.00000 -1.000 5.00000 -7.00000 -4.00000 1.000 5.00000 -7.00000 -1.00000 -1.000 5.00000 -7.00000 2.00000 1.000 5.00000 -7.00000 5.00000 -1.000 5.00000 -4.00000 -7.00000 1.000 5.00000 -4.00000 -4.00000 -1.000 5.00000 -4.00000 -1.00000 1.000 5.00000 -4.00000 2.00000 -1.000 5.00000 -4.00000 5.00000 1.000 5.00000 -1.00000 -7.00000 -1.000 5.00000 -1.00000 -4.00000 1.000 5.00000 -1.00000 -1.00000 -1.000 5.00000 -1.00000 2.00000 1.000 5.00000 -1.00000 5.00000 -1.000 5.00000 -1.00000 8.00000 1.000 5.00000 2.00000 -7.00000 -1.000 5.00000 2.00000 -4.00000 1.000 5.00000 2.00000 -1.00000 -1.000 5.00000 2.00000 2.00000 1.000 5.00000 2.00000 5.00000 -1.000 5.00000 2.00000 8.00000 1.000 5.00000 5.00000 -7.00000 -1.000 5.00000 5.00000 -4.00000 1.000 5.00000 5.00000 -1.00000 -1.000 5.00000 5.00000 2.00000 1.000 5.00000 5.00000 5.00000 -1.000 5.00000 8.00000 -1.00000 1.000 5.00000 8.00000 2.00000 -1.000 8.00000 -4.00000 -4.00000 1.000 8.00000 -4.00000 -1.00000 -1.000 8.00000 -4.00000 2.00000 1.000 8.00000 -1.00000 -4.00000 -1.000 8.00000 -1.00000 -1.00000 1.000 8.00000 -1.00000 2.00000 -1.000 8.00000 -1.00000 5.00000 1.000 8.00000 2.00000 -4.00000 -1.000 8.00000 2.00000 -1.00000 1.000 8.00000 2.00000 2.00000 -1.000 8.00000 2.00000 5.00000 1.000 8.00000 5.00000 -1.00000 -1.000 8.00000 5.00000 2.00000 1.000
追è¨:
ç¹ã«è¨è¿°ããªãã£ãã、åºåã¨ãã«ã®ã¼ã¯ããã³ã·ã£ã«ã¨ãã«ã®ã¼ãªã®ã§、念ã®ãã。ã¾ã、ããã§ã¯æéç©åã«ã¤ãã¦èæ ®ãã¦ããªã。NVEã¢ã³ãµã³ãã«(å®ã¨ãã«ã®ã¼)ã§ããã°、æéç©åã¯é度ãã«ã¬æ³ããã£ã¨ãå®è£ ããããããã«æã。dt/2ã§é度ãæ±ã、ããããdtã®åº§æ¨ãè¨ç®ã、ãã®åº§æ¨ããããã«dt/2ã§é度ãæ±ãã。
ã³ã¡ã³ã