Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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