|
| 1 | +// |
| 2 | +// (c) Copyright 2017 DESY,ESS |
| 3 | +// 2021 Eugen Wintersberger <[email protected]> |
| 4 | +// |
| 5 | +// This file is part of h5pp. |
| 6 | +// |
| 7 | +// This library is free software; you can redistribute it and/or modify it |
| 8 | +// under the terms of the GNU Lesser General Public License as published |
| 9 | +// by the Free Software Foundation; either version 2.1 of the License, or |
| 10 | +// (at your option) any later version. |
| 11 | +// |
| 12 | +// This library is distributed in the hope that it will be useful, but |
| 13 | +// WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY |
| 14 | +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
| 15 | +// License for more details. |
| 16 | +// |
| 17 | +// You should have received a copy of the GNU Lesser General Public License |
| 18 | +// along with this library; if not, write to the |
| 19 | +// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor |
| 20 | +// Boston, MA 02110-1301 USA |
| 21 | +// =========================================================================== |
| 22 | +// |
| 23 | +// Author: Jan Kotanski <[email protected]> |
| 24 | +// Eugen Wintersberger <[email protected]> |
| 25 | +// Created on: Nov 12, 2018 |
| 26 | +// |
| 27 | +#include <catch2/catch.hpp> |
| 28 | +#include <h5cpp/core/filesystem.hpp> |
| 29 | +#include <h5cpp/dataspace/hyperslab.hpp> |
| 30 | +#include <h5cpp/file/functions.hpp> |
| 31 | +#include <h5cpp/node/group.hpp> |
| 32 | +using namespace hdf5; |
| 33 | + |
| 34 | +#ifndef _MSC_VER |
| 35 | + |
| 36 | +const static long long unsigned int xdim = 867; |
| 37 | +const static long long unsigned int ydim = 700; |
| 38 | +const static long long unsigned int nframe = 33; |
| 39 | +static std::string filename = "dataset_io_speed.h5"; |
| 40 | +using UShorts = std::vector<unsigned short int>; |
| 41 | + |
| 42 | +hdf5::Dimensions current_dimensions(const hdf5::node::Dataset& dataset) { |
| 43 | + hdf5::dataspace::Simple dataspace(dataset.dataspace()); |
| 44 | + return dataspace.current_dimensions(); |
| 45 | +} |
| 46 | + |
| 47 | +class create { |
| 48 | + public: |
| 49 | + static property::FileCreationList fcpl() { |
| 50 | + return property::FileCreationList(); |
| 51 | + } |
| 52 | + static property::LinkCreationList lcpl() { |
| 53 | + return property::LinkCreationList(); |
| 54 | + } |
| 55 | + static property::DatasetAccessList dapl() { |
| 56 | + return property::DatasetAccessList(); |
| 57 | + } |
| 58 | + |
| 59 | + static property::DatasetCreationList dcpl() { |
| 60 | + property::DatasetCreationList dcpl; |
| 61 | + dcpl.layout(property::DatasetLayout::CHUNKED); |
| 62 | + dcpl.chunk({1, xdim, ydim}); |
| 63 | + return dcpl; |
| 64 | + } |
| 65 | + static property::FileAccessList fapl() { |
| 66 | + property::FileAccessList fapl; |
| 67 | +#if H5_VERSION_GE(1, 10, 0) |
| 68 | + fapl.library_version_bounds(property::LibVersion::LATEST, |
| 69 | + property::LibVersion::LATEST); |
| 70 | +#endif |
| 71 | + return fapl; |
| 72 | + } |
| 73 | + static file::File file() { |
| 74 | + return file::create(filename, file::AccessFlags::TRUNCATE, fcpl(), fapl()); |
| 75 | + } |
| 76 | + static dataspace::Simple ds(Dimensions current) { |
| 77 | + Dimensions max(current.size()); |
| 78 | + std::fill(std::begin(max), std::end(max), dataspace::Simple::UNLIMITED); |
| 79 | + return dataspace::Simple(current, max); |
| 80 | + } |
| 81 | + |
| 82 | + static UShorts buffer(size_t size) { |
| 83 | + UShorts b(size); |
| 84 | + std::fill(std::begin(b), std::end(b), 1); |
| 85 | + return b; |
| 86 | + } |
| 87 | +}; |
| 88 | + |
| 89 | +SCENARIO("Testing IO performance using different memory and file spaces") { |
| 90 | + auto ds_frame3 = create::ds({0, xdim, ydim}); // 3d dataspace for a 2D frame |
| 91 | + auto ds_all = |
| 92 | + create::ds({nframe, xdim, ydim}); // full dataspace of the block |
| 93 | + auto ds_frame2 = create::ds({xdim, ydim}); // 2d dataspace for a 2d frame |
| 94 | + auto dcpl = create::dcpl(); |
| 95 | + auto lcpl = create::lcpl(); |
| 96 | + auto dapl = create::dapl(); |
| 97 | + property::DatasetTransferList dtpl; |
| 98 | + auto dtype = datatype::create<unsigned short int>(); |
| 99 | + auto buffer_all = create::buffer(nframe * xdim * ydim); |
| 100 | + auto buffer_frame = create::buffer(xdim * ydim); |
| 101 | + auto buffer_selection = create::buffer(11 * xdim * ydim); |
| 102 | + |
| 103 | + GIVEN("A new HDF5 file") { |
| 104 | + auto file = create::file(); |
| 105 | + AND_GIVEN("an initially empty dataset") { |
| 106 | + node::Dataset dataset(file.root(), "data", dtype, ds_frame3, lcpl, dcpl, |
| 107 | + dapl); |
| 108 | + auto selection = dataspace::Hyperslab({{0, 0, 0}, {1, xdim, ydim}}); |
| 109 | + THEN("we can fill in frame by frame with full controll") { |
| 110 | + BENCHMARK("writing by single frame setting everything manually") { |
| 111 | + // here we set everything manually -> total control about what is |
| 112 | + // happening |
| 113 | + for (size_t frame_index = 0; frame_index < nframe; frame_index++) { |
| 114 | + dataset.extent(0, 1); |
| 115 | + selection.offset({frame_index, 0, 0}); |
| 116 | + auto file_space = dataset.dataspace(); |
| 117 | + file_space.selection(dataspace::SelectionOperation::SET, selection); |
| 118 | + dataset.write(buffer_frame, dtype, ds_frame2, file_space, dtpl); |
| 119 | + } |
| 120 | + }; |
| 121 | + } |
| 122 | + THEN("we can fill in frame by frame with derived ") { |
| 123 | + BENCHMARK("writing by single frame using auto setup") { |
| 124 | + // in this case the hyperlab is applied automatically and, more |
| 125 | + // important, the code derives every parameter of the memory |
| 126 | + // source by itself. |
| 127 | + for (size_t frame_index = 0; frame_index < nframe; frame_index++) { |
| 128 | + dataset.extent(0, 1); |
| 129 | + selection.offset({frame_index, 0, 0}); |
| 130 | + dataset.write(buffer_frame, selection); |
| 131 | + } |
| 132 | + }; |
| 133 | + } |
| 134 | + } |
| 135 | + AND_GIVEN("a dataset all elements present after construction") { |
| 136 | + node::Dataset dataset(file.root(), "data", dtype, ds_all, lcpl, dcpl, |
| 137 | + dapl); |
| 138 | + THEN("we can write the entire data at once") { |
| 139 | + BENCHMARK("writing the entire dataset at once") { |
| 140 | + dataset.write(buffer_all); |
| 141 | + }; |
| 142 | + AND_THEN("we can perform some read operations") { |
| 143 | + auto dims = current_dimensions(dataset); |
| 144 | + dataspace::Simple dspace = dataset.dataspace(); |
| 145 | + BENCHMARK("selecting the entire dataset block") { |
| 146 | + hdf5::Dimensions frameoffset{0, 0, 0}; |
| 147 | + hdf5::Dimensions frameblock{dims[0], dims[1], dims[2]}; |
| 148 | + hdf5::dataspace::Hyperslab selected_frames{frameoffset, frameblock}; |
| 149 | + return dataset.read(buffer_all, dtype, dspace, selected_frames); |
| 150 | + }; |
| 151 | + BENCHMARK("reading the entire dataset") { |
| 152 | + return dataset.read(buffer_all); |
| 153 | + }; |
| 154 | + BENCHMARK( |
| 155 | + "reading 11 frames with a hyperslab and a memory dataspace of " |
| 156 | + "the " |
| 157 | + "correct rank") { |
| 158 | + hdf5::dataspace::Hyperslab selection{{10, 0, 0}, |
| 159 | + {11, dims[1], dims[2]}}; |
| 160 | + dataspace::Simple memory_dataspace( |
| 161 | + Dimensions({11, dims[1], dims[2]})); |
| 162 | + return dataset.read(buffer_selection, dtype, memory_dataspace, |
| 163 | + selection); |
| 164 | + }; |
| 165 | + BENCHMARK("reading 11 frames with a default dataspace") { |
| 166 | + hdf5::dataspace::Hyperslab selection{{10, 0, 0}, |
| 167 | + {11, dims[1], dims[2]}}; |
| 168 | + return dataset.read(buffer_selection, selection); |
| 169 | + }; |
| 170 | + } |
| 171 | + } |
| 172 | + } |
| 173 | + } |
| 174 | + |
| 175 | + // create_initial_datafile(); |
| 176 | + /* |
| 177 | + GIVEN("The data file with the data to read") { |
| 178 | + auto file = file::open(filename, file::AccessFlags::READONLY); |
| 179 | + auto dataset = file.root().get_dataset("/data"); |
| 180 | + auto dtype = dataset.datatype(); |
| 181 | + }*/ |
| 182 | +} |
| 183 | +#endif |
0 commit comments