CudaConstantMemory.cpp
上传用户:chinafayin
上传日期:2022-04-05
资源大小:153k
文件大小:6k
源码类别:

并行计算

开发平台:

Visual C++

  1. /*
  2.     FastGrid (formerly AutoGrid)
  3.     Copyright (C) 2009 The Scripps Research Institute. All rights reserved.
  4.     Copyright (C) 2009 Masaryk University. All rights reserved.
  5.     AutoGrid is a Trade Mark of The Scripps Research Institute.
  6.     This program is free software; you can redistribute it and/or
  7.     modify it under the terms of the GNU General Public License
  8.     as published by the Free Software Foundation; either version 2
  9.     of the License, or (at your option) any later version.
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17. */
  18. #include <algorithm>
  19. #include "CudaConstantMemory.h"
  20. struct CudaConstantMemory::AtomsConstMem
  21. {
  22.     float4 atoms[4096];
  23.     int numAtoms;
  24. };
  25. CudaConstantMemory::CudaConstantMemory(cudaStream_t stream, CudaInternalAPI *api): api(api), atomsHost(0), stream(stream),
  26.     zIndexArray(0), numAtomSubsets(1), currentZSlice(0), epsilonHost(0)
  27. {
  28.     CUDA_SAFE_CALL(cudaMallocHost((void**)&paramsHost, sizeof(Params)));
  29. }
  30. CudaConstantMemory::~CudaConstantMemory()
  31. {
  32.     if (epsilonHost)
  33.     {
  34.         CUDA_SAFE_CALL(cudaFreeHost(epsilonHost));
  35.         CUDA_SAFE_CALL(cudaFree(params.epsilonDevice));
  36.     }
  37.     CUDA_SAFE_CALL(cudaFreeHost(paramsHost));
  38.     if (zIndexArray)
  39.         CUDA_SAFE_CALL(cudaFreeHost(zIndexArray));
  40.     if (atomsHost)
  41.         CUDA_SAFE_CALL(cudaFreeHost(atomsHost));
  42. }
  43. void CudaConstantMemory::initDistDepDielLookUpTable(const double *epsilon)
  44. {
  45.     int size = sizeof(float) * MAX_DIST;
  46.     CUDA_SAFE_CALL(cudaMallocHost((void**)&epsilonHost, size));
  47.     CUDA_SAFE_CALL(cudaMalloc((void**)&params.epsilonDevice, size));
  48.     paramsHost->epsilonDevice = params.epsilonDevice;
  49.     std::transform(epsilon, epsilon + MAX_DIST, epsilonHost, typecast<float, double>);
  50.     CUDA_SAFE_CALL(cudaMemcpyAsync(params.epsilonDevice, epsilonHost, size, cudaMemcpyHostToDevice, stream));
  51.     api->setDistDepDielLookUpTable(&paramsHost->epsilonDevice, stream);
  52. }
  53. void CudaConstantMemory::setGridMapParameters(const Vec3i &numGridPointsDiv2, double gridSpacing,
  54.                                               const Vec3i &numGridPointsPadded, float *energiesDevice)
  55. {
  56.     params.numGridPointsPadded = make_int3(numGridPointsPadded.x, numGridPointsPadded.y, numGridPointsPadded.z);
  57.     params.gridSpacing = float(gridSpacing);
  58.     params.energiesDevice = energiesDevice;
  59.     params.numGridPointsDiv2 = make_int3(numGridPointsDiv2.x, numGridPointsDiv2.y, numGridPointsDiv2.z);
  60.     *paramsHost = params;
  61.     api->setGridMap(&paramsHost->numGridPointsPadded, &paramsHost->numGridPointsDiv2,
  62.                                    &paramsHost->gridSpacing, &paramsHost->energiesDevice, stream);
  63. }
  64. void CudaConstantMemory::initAtoms(const Vec4d *atoms, int numAtoms, bool calculateSlicesSeparately)
  65. {
  66.     numAtomSubsets = (numAtoms - 1) / api->numAtomsPerKernel + 1;
  67.     int kernelCalls = calculateSlicesSeparately ? params.numGridPointsPadded.z : 1;
  68.     CUDA_SAFE_CALL(cudaMallocHost((void**)&atomsHost, sizeof(AtomsConstMem) * kernelCalls * numAtomSubsets));
  69.     if (calculateSlicesSeparately) // Initialize atoms for later calculating slices separately
  70.     {
  71.         initZIndexArray();
  72.         for (int z = 0; z < params.numGridPointsPadded.z; z++)
  73.         {
  74.             // Set the pointer to memory of this slice
  75.             AtomsConstMem *atomConstMemZBase = atomsHost + z * numAtomSubsets;
  76.             // For each subset numAtomsPerKernel long
  77.             for (int iaStart = 0, i = 0; iaStart < numAtoms; iaStart += api->numAtomsPerKernel, i++)
  78.             {
  79.                 int numAtomsInSubset = Mathi::Min(numAtoms - iaStart, api->numAtomsPerKernel);
  80.                 AtomsConstMem &thisAtomConstMem = atomConstMemZBase[i];
  81.                 thisAtomConstMem.numAtoms = numAtomsInSubset;
  82.                 // For each atom in the subset
  83.                 for (int ia = 0; ia < numAtomsInSubset; ia++)
  84.                 {
  85.                     const Vec4d &atom = atoms[iaStart + ia];
  86.                     // Copy X, Y, Z, and the charge
  87.                     thisAtomConstMem.atoms[ia].x = float(atom.x);
  88.                     thisAtomConstMem.atoms[ia].y = float(atom.y);
  89.                     thisAtomConstMem.atoms[ia].z = float(atom.z);
  90.                     thisAtomConstMem.atoms[ia].w = float(atom.w);
  91.                 }
  92.             }
  93.         }
  94.     }
  95.     else // Initialize atoms for later calculating the entire gridmap in one kernel call
  96.     {
  97.         // For each subset numAtomsPerKernel long
  98.         for (int iaStart = 0, i = 0; iaStart < numAtoms; iaStart += api->numAtomsPerKernel, i++)
  99.         {
  100.             int numAtomsInSubset = Mathi::Min(numAtoms - iaStart, api->numAtomsPerKernel);
  101.             AtomsConstMem &thisAtomConstMem = atomsHost[i];
  102.             thisAtomConstMem.numAtoms = numAtomsInSubset;
  103.             // For each atom in the subset
  104.             for (int ia = 0; ia < numAtomsInSubset; ia++)
  105.             {
  106.                 const Vec4d &atom = atoms[iaStart + ia];
  107.                 // Copy X, Y, Z, and the charge
  108.                 thisAtomConstMem.atoms[ia].x = float(atom.x);
  109.                 thisAtomConstMem.atoms[ia].y = float(atom.y);
  110.                 thisAtomConstMem.atoms[ia].z = float(atom.z);
  111.                 thisAtomConstMem.atoms[ia].w = float(atom.w);
  112.             }
  113.         }
  114.     }
  115. }
  116. void CudaConstantMemory::initZIndexArray()
  117. {
  118.     int numSlices = params.numGridPointsPadded.z;
  119.     // Reserve memory for each offseted output index of a slice and precalculate
  120.     CUDA_SAFE_CALL(cudaMallocHost((void**)&zIndexArray, sizeof(int) * numSlices));
  121.     for (int z = 0; z < numSlices; z++)
  122.         zIndexArray[z] = z;
  123. }
  124. void CudaConstantMemory::setZSlice(int z)
  125. {
  126.     currentZSlice = z;
  127.     // Set an offset of output index to constant memory
  128.     api->setSlice(zIndexArray + z, stream);
  129. }
  130. void CudaConstantMemory::setAtomConstMem(int atomSubsetIndex)
  131. {
  132.     AtomsConstMem *thisAtomConstMem = atomsHost + currentZSlice * numAtomSubsets + atomSubsetIndex;
  133.     api->setAtoms(&thisAtomConstMem->numAtoms, thisAtomConstMem->atoms, stream);
  134. }