|
| 1 | +#include <iostream> |
| 2 | +#include <fstream> |
| 3 | +#include <Eigen/Core> |
| 4 | +#include <alpaka/alpaka.hpp> |
| 5 | + |
| 6 | +#include "DataFormats/GeometryVector/interface/GlobalPoint.h" |
| 7 | +#include "DataFormats/GeometryVector/interface/GlobalVector.h" |
| 8 | +#include "FWCore/Utilities/interface/FileInPath.h" |
| 9 | +#include "FWCore/Utilities/interface/Exception.h" |
| 10 | +#include "FWCore/Utilities/interface/stringize.h" |
| 11 | +#include "HeterogeneousCore/AlpakaInterface/interface/config.h" |
| 12 | +#include "HeterogeneousCore/AlpakaInterface/interface/memory.h" |
| 13 | +#include "HeterogeneousCore/AlpakaInterface/interface/workdivision.h" |
| 14 | +#include "MagneticField/ParametrizedEngine/interface/ParabolicParametrizedMagneticField.h" |
| 15 | + |
| 16 | +using namespace edm; |
| 17 | +using namespace std; |
| 18 | +using namespace ALPAKA_ACCELERATOR_NAMESPACE; |
| 19 | +using namespace magneticFieldParabolicPortable; |
| 20 | +using Vector3f = Eigen::Matrix<float, 3, 1>; |
| 21 | + |
| 22 | +struct MagneticFieldKernel { |
| 23 | + template <typename TAcc, typename T> |
| 24 | + ALPAKA_FN_ACC void operator()(TAcc const& acc, T const* __restrict__ in, T* __restrict__ out, size_t size) const { |
| 25 | + for (auto index : cms::alpakatools::uniform_elements(acc, size)) { |
| 26 | + out[index](0) = 0; |
| 27 | + out[index](1) = 0; |
| 28 | + out[index](2) = magneticFieldAtPoint(in[index]); |
| 29 | + } |
| 30 | + } |
| 31 | +}; |
| 32 | + |
| 33 | +int main() { |
| 34 | + // get the list of devices on the current platform |
| 35 | + auto const& devices = cms::alpakatools::devices<Platform>(); |
| 36 | + if (devices.empty()) { |
| 37 | + std::cerr << "No devices available for the " EDM_STRINGIZE(ALPAKA_ACCELERATOR_NAMESPACE) " backend, " |
| 38 | + "the test will be skipped.\n"; |
| 39 | + exit(EXIT_FAILURE); |
| 40 | + } |
| 41 | + |
| 42 | + ifstream file; |
| 43 | + edm::FileInPath mydata("MagneticField/Engine/data/Regression/referenceField_160812_RII_3_8T.bin"); |
| 44 | + file.open(mydata.fullPath().c_str(), ios::binary); |
| 45 | + |
| 46 | + int count = 0; |
| 47 | + float px, py, pz; |
| 48 | + float bx, by, bz; |
| 49 | + vector<Vector3f> points; |
| 50 | + vector<GlobalVector> referenceB_vec; |
| 51 | + |
| 52 | + int numberOfPoints = 100; |
| 53 | + points.reserve(numberOfPoints); |
| 54 | + referenceB_vec.reserve(numberOfPoints); |
| 55 | + do { |
| 56 | + if (!(file.read((char*)&px, sizeof(float)) && file.read((char*)&py, sizeof(float)) && |
| 57 | + file.read((char*)&pz, sizeof(float)) && file.read((char*)&bx, sizeof(float)) && |
| 58 | + file.read((char*)&by, sizeof(float)) && file.read((char*)&bz, sizeof(float)))) |
| 59 | + break; |
| 60 | + |
| 61 | + const auto point = Vector3f(px, py, pz); |
| 62 | + if (!isValid(point)) |
| 63 | + continue; |
| 64 | + |
| 65 | + points.push_back(Vector3f(px, py, pz)); |
| 66 | + referenceB_vec.push_back(GlobalVector(bx, by, bz)); |
| 67 | + count++; |
| 68 | + } while (count < numberOfPoints); |
| 69 | + |
| 70 | + const size_t size = points.size(); |
| 71 | + // allocate the input and output host buffer in pinned memory accessible by the Platform devices |
| 72 | + auto points_host = cms::alpakatools::make_host_buffer<Vector3f[], Platform>(size); |
| 73 | + auto field_host = cms::alpakatools::make_host_buffer<Vector3f[], Platform>(size); |
| 74 | + // fill the input buffers, and the output buffer with zeros |
| 75 | + for (size_t i = 0; i < size; ++i) { |
| 76 | + points_host[i] = points[i]; |
| 77 | + field_host[i] = Vector3f::Zero(); |
| 78 | + } |
| 79 | + |
| 80 | + float resolution = 0.2; |
| 81 | + float maxdelta = 0.; |
| 82 | + int fail = 0; |
| 83 | + |
| 84 | + // run the test on each device |
| 85 | + for (auto const& device : devices) { |
| 86 | + auto queue = Queue(device); |
| 87 | + // allocate input and output buffers on the device |
| 88 | + auto points_dev = cms::alpakatools::make_device_buffer<Vector3f[]>(queue, size); |
| 89 | + auto field_dev = cms::alpakatools::make_device_buffer<Vector3f[]>(queue, size); |
| 90 | + |
| 91 | + // copy the input data to the device; the size is known from the buffer objects |
| 92 | + alpaka::memcpy(queue, points_dev, points_host); |
| 93 | + // fill the output buffer with zeros; the size is known from the buffer objects |
| 94 | + alpaka::memset(queue, field_dev, 0.); |
| 95 | + |
| 96 | + auto workDiv = cms::alpakatools::make_workdiv<Acc1D>(1, size); |
| 97 | + alpaka::exec<Acc1D>(queue, workDiv, MagneticFieldKernel{}, points_dev.data(), field_dev.data(), size); |
| 98 | + |
| 99 | + // copy the results from the device to the host |
| 100 | + alpaka::memcpy(queue, field_host, field_dev); |
| 101 | + |
| 102 | + // wait for the kernel and the potential copy to complete |
| 103 | + alpaka::wait(queue); |
| 104 | + |
| 105 | + // check the results |
| 106 | + for (uint i = 0; i < points.size(); i++) { |
| 107 | + const auto& point = points[i]; |
| 108 | + const auto& referenceB = referenceB_vec[i]; |
| 109 | + GlobalVector parametricB(field_host[i](0), field_host[i](1), field_host[i](2)); |
| 110 | + float delta = (referenceB - parametricB).mag(); |
| 111 | + if (delta > resolution) { |
| 112 | + ++fail; |
| 113 | + if (delta > maxdelta) |
| 114 | + maxdelta = delta; |
| 115 | + if (fail < 10) { |
| 116 | + const GlobalPoint gp(point(0), point(1), point(2)); |
| 117 | + cout << " Discrepancy at point # " << i + 1 << ": " << gp << ", R " << gp.perp() << ", Phi " << gp.phi() |
| 118 | + << ", delta: " << referenceB - parametricB << " " << delta << endl; |
| 119 | + cout << " Reference: " << referenceB << ", Approximation: " << parametricB << endl; |
| 120 | + } else if (fail == 10) { |
| 121 | + cout << "..." << endl; |
| 122 | + } |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + if (fail != 0) { |
| 127 | + cout << "MF regression found: " << fail << " failures; max delta = " << maxdelta << endl; |
| 128 | + exit(EXIT_FAILURE); |
| 129 | + } |
| 130 | + } |
| 131 | +} |
0 commit comments