-
Notifications
You must be signed in to change notification settings - Fork 15
Avoid dynamic allocation with H5Sselect_hyperslab
#101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,15 +31,18 @@ inline DataSpace::DataSpace(const std::vector<size_t>& dims) | |
| : DataSpace(dims.begin(), dims.end()) {} | ||
|
|
||
| template <size_t N> | ||
| inline DataSpace::DataSpace(const std::array<size_t, N>& dims) | ||
| : DataSpace(dims.begin(), dims.end()) {} | ||
| constexpr DataSpace::DataSpace(const std::array<size_t, N>& dims) { | ||
| std::array<hsize_t, N> real_dims; | ||
| std::copy(dims.begin(), dims.end(), real_dims.begin()); | ||
| _hid = detail::h5s_create_simple(static_cast<int>(N), real_dims.data(), nullptr); | ||
| } | ||
antonysigma marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| inline DataSpace::DataSpace(const std::initializer_list<size_t>& items) | ||
| : DataSpace(std::vector<size_t>(items)) {} | ||
|
|
||
| template <typename... Args> | ||
| inline DataSpace::DataSpace(size_t dim1, Args... dims) | ||
| : DataSpace(std::vector<size_t>{dim1, static_cast<size_t>(dims)...}) {} | ||
| : DataSpace(std::array{dim1, static_cast<size_t>(dims)...}) {} | ||
|
||
|
|
||
| template <class IT, typename> | ||
| inline DataSpace::DataSpace(const IT begin, const IT end) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -229,18 +229,18 @@ inline Selection SliceTraits<Derivate>::select(const HyperSlab& hyper_slab, | |
| } | ||
|
|
||
| template <typename Derivate> | ||
| inline Selection SliceTraits<Derivate>::select(const HyperSlab& hyper_slab) const { | ||
| template <class HyperSlabInterface> | ||
| inline Selection SliceTraits<Derivate>::select(const HyperSlabInterface& hyper_slab) const { | ||
| const auto& slice = static_cast<const Derivate&>(*this); | ||
| auto filespace = slice.getSpace(); | ||
| filespace = hyper_slab.apply(filespace); | ||
|
|
||
| auto n_elements = detail::h5s_get_select_npoints(filespace.getId()); | ||
| auto memspace = DataSpace(std::array<size_t, 1>{size_t(n_elements)}); | ||
| const auto n_elements = detail::h5s_get_select_npoints(filespace.getId()); | ||
| auto memspace = DataSpace{static_cast<size_t>(n_elements)}; | ||
|
|
||
| return detail::make_selection(memspace, filespace, details::get_dataset(slice)); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As you might have noticed I'm not so keen on having both a statically sized version and fixed-sized version. Especially, because it's currently not done for performance reasons and HighFive is very consistent about using Now for the good news: we could use SFINAE for @antonysigma Would this work for you? The SFINAE part isn't strictly needed, in a first version an unconstrained template parameter would suffice. That way if you don't feel like fighting SFINAE, I can take care of it later.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re: moving Re: SFINAE for
Yes, help wanted to tighten the constraints eventually.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll first try with |
||
|
|
||
|
|
||
| template <typename Derivate> | ||
| inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& offset, | ||
| const std::vector<size_t>& count, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| /* | ||
| * Copyright (c), 2017, Adrien Devresse | ||
| * | ||
| * Distributed under the Boost Software License, Version 1.0. | ||
| * (See accompanying file LICENSE_1_0.txt or copy at | ||
| * http://www.boost.org/LICENSE_1_0.txt) | ||
| * | ||
| */ | ||
|
||
| #include <functional> | ||
| #include <iostream> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| #include <highfive/highfive.hpp> | ||
|
|
||
| namespace { | ||
| template <size_t Rank> | ||
| struct RegularHyperSlabNoMalloc { | ||
| constexpr size_t rank() const { | ||
| return Rank; | ||
| } | ||
|
|
||
| /// Dimensions when all gaps are removed. | ||
| constexpr std::array<size_t, Rank> packedDims() const { | ||
| auto dims = std::array<size_t, Rank>{}; | ||
|
|
||
| for (size_t i = 0; i < Rank; ++i) { | ||
| dims[i] = count[i] * (block ? (*block)[i] : 1); | ||
| } | ||
|
|
||
| return dims; | ||
| } | ||
|
|
||
| HighFive::DataSpace apply(const HighFive::DataSpace& space_) const { | ||
| auto space = space_.clone(); | ||
| const auto error_code = H5Sselect_hyperslab(space.getId(), | ||
| H5S_SELECT_SET, | ||
| offset.data(), | ||
| stride ? stride->data() : nullptr, | ||
| count.data(), | ||
| block ? block->data() : nullptr); | ||
|
|
||
| if (error_code < 0) { | ||
| HighFive::HDF5ErrMapper::ToException<HighFive::DataSpaceException>( | ||
| "Unable to select hyperslab"); | ||
| } | ||
| return space; | ||
| } | ||
|
|
||
| std::array<hsize_t, Rank> offset{}; | ||
| std::array<hsize_t, Rank> count{}; | ||
| std::optional<std::array<hsize_t, Rank>> stride{std::nullopt}; | ||
| std::optional<std::array<hsize_t, Rank>> block{std::nullopt}; | ||
| }; | ||
| } // namespace | ||
|
|
||
| int main(void) { | ||
| using namespace HighFive; | ||
|
|
||
| // Create a new file using the default property lists. | ||
| // | ||
| // Note: In C++14, using braces in constructor implies "explicit" keyword. Compiler logs will | ||
| // warn about possible implicit type conversion that may involves transient memory allocations. | ||
| File file{"select_partial_example_cpp17.h5", File::ReadWrite | File::Create | File::Truncate}; | ||
|
|
||
| // we have some example values in a 2D vector 2x5 | ||
| // Specifying the inner dimensions as std::array ensures that the two-dimensional data is | ||
| // contiguous, so that the compiler will only invoke one single memory allocation. The | ||
| // compiler also ensures the column counts are identical. | ||
| // | ||
| // Note: C++17 required. | ||
| const std::vector values{std::array{1.0, 2.0, 4.0, 8.0, 16.0}, | ||
| {32.0, 64.0, 128.0, 256.0, 512.0}}; | ||
|
|
||
| // let's create a dataset of this size | ||
| DataSet dataset = file.createDataSet<double>("dset", DataSpace::From(values)); | ||
| // and write them | ||
| dataset.write(values); | ||
|
|
||
|
|
||
| // now we read back 2x2 values after an offset of 0x2 | ||
| // Notice that std::array lives in the stack space memory. No memory allocation required. | ||
| std::array<std::array<double, 2>, 2> result; | ||
|
|
||
| // Specify the selection without any memory allocations. | ||
| dataset.select(RegularHyperSlabNoMalloc<2>{{0, 2}, {2, 2}}).read_raw(result.front().data()); | ||
|
|
||
| // we print out 4 values | ||
| for (auto i: result) { | ||
| for (auto j: i) { | ||
| std::cout << ' ' << j; | ||
| } | ||
| std::cout << '\n'; | ||
| } | ||
|
|
||
| return 0; // successfully terminated | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.