Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-03-30 08:50:55

0001 #include "RecoLocalCalo/HGCalRecProducers/plugins/HeterogeneousHGCalEEConditions.h"
0002 
0003 namespace {
0004   double*& select_pointer_d(cp::HeterogeneousHGCalEEParameters* cpuObject, const unsigned& item) {
0005     switch (item) {
0006       case 0:
0007         return cpuObject->cellFineX_;
0008       case 1:
0009         return cpuObject->cellFineY_;
0010       case 2:
0011         return cpuObject->cellCoarseX_;
0012       case 3:
0013         return cpuObject->cellCoarseY_;
0014       default:
0015         throw cms::Exception("HeterogeneousHGCalEEConditionsWrapper") << "select_pointer_d(heterogeneous): no item.";
0016         return cpuObject->cellCoarseY_;
0017     }
0018   }
0019 
0020   const std::vector<double>& select_pointer_d(const HGCalParameters* cpuObject, const unsigned& item) {
0021     switch (item) {
0022       case 0:
0023         return cpuObject->cellFineX_;
0024       case 1:
0025         return cpuObject->cellFineY_;
0026       case 2:
0027         return cpuObject->cellCoarseX_;
0028       case 3:
0029         return cpuObject->cellCoarseY_;
0030       default:
0031         throw cms::Exception("HeterogeneousHGCalEEConditionsWrapper")
0032             << "select_pointer_d(non-heterogeneous): no item.";
0033         return cpuObject->cellCoarseY_;
0034     }
0035   }
0036 
0037   int32_t*& select_pointer_i(cp::HeterogeneousHGCalEEParameters* cpuObject, const unsigned& item) {
0038     switch (item) {
0039       case 4:
0040         return cpuObject->waferTypeL_;
0041       default:
0042         throw cms::Exception("HeterogeneousHGCalEEConditionsWrapper") << "select_pointer_i(heterogeneous): no item.";
0043         return cpuObject->waferTypeL_;
0044     }
0045   }
0046 
0047   const std::vector<int32_t>& select_pointer_i(const HGCalParameters* cpuObject, const unsigned& item) {
0048     switch (item) {
0049       case 4:
0050         return cpuObject->waferTypeL_;
0051       default:
0052         throw cms::Exception("HeterogeneousHGCalEEConditionsWrapper")
0053             << "select_pointer_i(non-heterogeneous): no item.";
0054         return cpuObject->waferTypeL_;
0055     }
0056   }
0057 }  // namespace
0058 
0059 HeterogeneousHGCalEEConditionsWrapper::HeterogeneousHGCalEEConditionsWrapper(const HGCalParameters* cpuHGCalParameters) {
0060   calculate_memory_bytes(cpuHGCalParameters);
0061 
0062   chunk_ = std::accumulate(this->sizes_.begin(), this->sizes_.end(), 0);  //total memory required in bytes
0063   cudaCheck(cudaMallocHost(&this->params_.cellFineX_, chunk_));
0064 
0065   //store cumulative sum in bytes and convert it to sizes in units of C++ typesEE, i.e., number if items to be transferred to GPU
0066   std::vector<size_t> cumsum_sizes(this->sizes_.size() + 1, 0);  //starting with zero
0067   std::partial_sum(this->sizes_.begin(), this->sizes_.end(), cumsum_sizes.begin() + 1);
0068   for (unsigned i(1); i < cumsum_sizes.size(); ++i)  //start at second element (the first is zero)
0069   {
0070     unsigned typesEEsize(0);
0071     if (cp::typesEE[i - 1] == cp::HeterogeneousHGCalEEParametersType::Double)
0072       typesEEsize = sizeof(double);
0073     else if (cp::typesEE[i - 1] == cp::HeterogeneousHGCalEEParametersType::Int32_t)
0074       typesEEsize = sizeof(int32_t);
0075     else
0076       throw cms::Exception("HeterogeneousHGCalEEConditionsWrapper") << "Wrong HeterogeneousHGCalParameters type";
0077     cumsum_sizes[i] /= typesEEsize;
0078   }
0079 
0080   for (unsigned j(0); j < this->sizes_.size(); ++j) {
0081     //setting the pointers
0082     if (j != 0) {
0083       const unsigned jm1(j - 1);
0084       if (cp::typesEE[jm1] == cp::HeterogeneousHGCalEEParametersType::Double and
0085           cp::typesEE[j] == cp::HeterogeneousHGCalEEParametersType::Double)
0086         ::select_pointer_d(&this->params_, j) = ::select_pointer_d(&this->params_, jm1) + this->sizes_[jm1];
0087       else if (cp::typesEE[jm1] == cp::HeterogeneousHGCalEEParametersType::Double and
0088                cp::typesEE[j] == cp::HeterogeneousHGCalEEParametersType::Int32_t)
0089         ::select_pointer_i(&this->params_, j) =
0090             reinterpret_cast<int32_t*>(::select_pointer_d(&this->params_, jm1) + this->sizes_[jm1]);
0091     }
0092 
0093     //copying the pointers' content
0094     for (unsigned i(cumsum_sizes[j]); i < cumsum_sizes[j + 1]; ++i) {
0095       unsigned index(i - cumsum_sizes[j]);
0096       if (cp::typesEE[j] == cp::HeterogeneousHGCalEEParametersType::Double) {
0097         ::select_pointer_d(&this->params_, j)[index] = ::select_pointer_d(cpuHGCalParameters, j)[index];
0098       } else if (cp::typesEE[j] == cp::HeterogeneousHGCalEEParametersType::Int32_t)
0099         ::select_pointer_i(&this->params_, j)[index] = ::select_pointer_i(cpuHGCalParameters, j)[index];
0100       else
0101         throw cms::Exception("HeterogeneousHGCalEEConditionsWrapper") << "Wrong HeterogeneousHGCalParameters type";
0102     }
0103   }
0104 }
0105 
0106 void HeterogeneousHGCalEEConditionsWrapper::calculate_memory_bytes(const HGCalParameters* cpuHGCalParameters) {
0107   size_t npointers = hgcal_conditions::parameters::typesEE.size();
0108   std::vector<size_t> sizes(npointers);
0109   for (unsigned i(0); i < npointers; ++i) {
0110     if (cp::typesEE[i] == cp::HeterogeneousHGCalEEParametersType::Double)
0111       sizes[i] = ::select_pointer_d(cpuHGCalParameters, i).size();
0112     else
0113       sizes[i] = ::select_pointer_i(cpuHGCalParameters, i).size();
0114   }
0115 
0116   std::vector<size_t> sizes_units(npointers);
0117   for (unsigned i(0); i < npointers; ++i) {
0118     if (cp::typesEE[i] == cp::HeterogeneousHGCalEEParametersType::Double)
0119       sizes_units[i] = sizeof(double);
0120     else if (cp::typesEE[i] == cp::HeterogeneousHGCalEEParametersType::Int32_t)
0121       sizes_units[i] = sizeof(int32_t);
0122   }
0123 
0124   //element by element multiplication
0125   this->sizes_.resize(npointers);
0126   std::transform(sizes.begin(), sizes.end(), sizes_units.begin(), this->sizes_.begin(), std::multiplies<size_t>());
0127 }
0128 
0129 HeterogeneousHGCalEEConditionsWrapper::~HeterogeneousHGCalEEConditionsWrapper() {
0130   cudaCheck(cudaFreeHost(this->params_.cellFineX_));
0131 }
0132 
0133 //I could use template specializations
0134 //try to use std::variant in the future to avoid similar functions with different return values
0135 
0136 hgcal_conditions::HeterogeneousEEConditionsESProduct const*
0137 HeterogeneousHGCalEEConditionsWrapper::getHeterogeneousConditionsESProductAsync(cudaStream_t stream) const {
0138   // cms::cuda::ESProduct<T> essentially holds an array of GPUData objects,
0139   // one per device. If the data have already been transferred to the
0140   // current device (or the transfer has been queued), the helper just
0141   // returns a reference to that GPUData object. Otherwise, i.e. data are
0142   // not yet on the current device, the helper calls the lambda to do the
0143   // necessary memory allocations and to queue the transfers.
0144   auto const& data = gpuData_.dataForCurrentDeviceAsync(stream, [this](GPUData& data, cudaStream_t stream) {
0145     // Allocate the payload object on pinned host memory.
0146     cudaCheck(cudaMallocHost(&data.host, sizeof(hgcal_conditions::HeterogeneousEEConditionsESProduct)));
0147     // Allocate the payload array(s) on device memory.
0148     cudaCheck(cudaMalloc(&(data.host->params.cellFineX_), chunk_));
0149 
0150     // Allocate the payload object on the device memory.
0151     cudaCheck(cudaMalloc(&data.device, sizeof(hgcal_conditions::HeterogeneousEEConditionsESProduct)));
0152     // Transfer the payload, first the array(s) ...
0153     cudaCheck(cudaMemcpyAsync(
0154         data.host->params.cellFineX_, this->params_.cellFineX_, chunk_, cudaMemcpyHostToDevice, stream));
0155 
0156     for (unsigned j(0); j < this->sizes_.size() - 1; ++j) {
0157       if (cp::typesEE[j] == cp::HeterogeneousHGCalEEParametersType::Double and
0158           cp::typesEE[j + 1] == cp::HeterogeneousHGCalEEParametersType::Double)
0159         ::select_pointer_d(&(data.host->params), j + 1) = ::select_pointer_d(&(data.host->params), j) + this->sizes_[j];
0160       else if (cp::typesEE[j] == cp::HeterogeneousHGCalEEParametersType::Double and
0161                cp::typesEE[j + 1] == cp::HeterogeneousHGCalEEParametersType::Int32_t)
0162         ::select_pointer_i(&(data.host->params), j + 1) =
0163             reinterpret_cast<int32_t*>(::select_pointer_d(&(data.host->params), j) + this->sizes_[j]);
0164       else
0165         throw cms::Exception("HeterogeneousHGCalEEConditionsWrapper")
0166             << "compare this functions' logic with hgcal_conditions::parameters::typesEE";
0167     }
0168 
0169     // ... and then the payload object
0170     cudaCheck(cudaMemcpyAsync(data.device,
0171                               data.host,
0172                               sizeof(hgcal_conditions::HeterogeneousEEConditionsESProduct),
0173                               cudaMemcpyHostToDevice,
0174                               stream));
0175   });  //gpuData_.dataForCurrentDeviceAsync
0176 
0177   // Returns the payload object on the memory of the current device
0178   return data.device;
0179 }
0180 
0181 // Destructor frees all member pointers
0182 HeterogeneousHGCalEEConditionsWrapper::GPUData::~GPUData() {
0183   if (host != nullptr) {
0184     cudaCheck(cudaFree(host->params.cellFineX_));
0185     cudaCheck(cudaFreeHost(host));
0186   }
0187   cudaCheck(cudaFree(device));
0188 }