Skip to content

Commit

Permalink
Merge making new Accessors independent of Ginkgo
Browse files Browse the repository at this point in the history
Move the following accessors to the global folder `accessor/`:
- `scaled_reduced_row_major`
- `reduced_row_major`
- `row_major` (the newly added one with arbitrary dimensionality)
- `block_col_major`

A separate `range` was also implemented because it is needed to use
the accessors.

Additionally, the following improvements / updates were performed:
- Move each accessor to its own file
- Add a subdirectory `core/test/accessor`, where the accessors are
  tested. The tests also make sure that the accessors are independent
  of Ginkgo since they don't link against Ginkgo
- Create separate test file for each accessor


Related PR: #708
  • Loading branch information
Thomas Grützmacher authored Mar 16, 2021
2 parents b293b9f + b11ca27 commit 3e31cc0
Show file tree
Hide file tree
Showing 31 changed files with 3,887 additions and 3,180 deletions.
794 changes: 794 additions & 0 deletions accessor/accessor_helper.hpp

Large diffs are not rendered by default.

190 changes: 94 additions & 96 deletions core/base/accessor_references.hpp → accessor/accessor_references.hpp

Large diffs are not rendered by default.

208 changes: 208 additions & 0 deletions accessor/block_col_major.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*******************************<GINKGO LICENSE>******************************
Copyright (c) 2017-2021, the Ginkgo authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************<GINKGO LICENSE>*******************************/

#ifndef GKO_ACCESSOR_BLOCK_COL_MAJOR_HPP_
#define GKO_ACCESSOR_BLOCK_COL_MAJOR_HPP_

#include <array>

#include "accessor_helper.hpp"
#include "range.hpp"
#include "utils.hpp"


namespace gko {
namespace acc {


/**
* A bridge between a range and a block-column-major memory layout.
*
* Only the innermost two dimensions are regarded as defining
* a column-major matrix, and the rest of the dimensions are treated
* identically to \ref row_major.
*
* You should not try to explicitly create an instance of this accessor.
* Instead, supply it as a template parameter to a range, and pass the
* constructor parameters for this class to the range (it will forward it to
* this class).
*
* @tparam ValueType type of values this accessor returns
* @tparam Dimensionality number of dimensions of this accessor
*/
template <typename ValueType, size_type Dimensionality>
class block_col_major {
public:
friend class range<block_col_major>;

static_assert(Dimensionality != 0,
"This accessor does not support a dimensionality of 0!");
static_assert(Dimensionality != 1,
"Please use row_major accessor for 1D ranges.");

/**
* Number of dimensions of the accessor.
*/
static constexpr size_type dimensionality = Dimensionality;

/**
* Type of values returned by the accessor.
*/
using value_type = ValueType;

/**
* Type of underlying data storage.
*/
using data_type = value_type *;

using const_accessor = block_col_major<const ValueType, Dimensionality>;
using stride_type = std::array<size_type, dimensionality - 1>;
using length_type = std::array<size_type, dimensionality>;

protected:
/**
* Creates a block_col_major accessor.
*
* @param data pointer to the block of memory containing the data
* @param lengths size / length of the accesses of each dimension
* @param stride distance (in elements) between starting positions of
* the dimensions (i.e.
* `x_1 * stride_1 + x_2 * stride_2 * ... + x_(n-1) + x_n * stride_(n-1)`
* points to the element at (x_1, x_2, ..., x_n))
*/
constexpr GKO_ACC_ATTRIBUTES explicit block_col_major(length_type size,
data_type data,
stride_type stride)
: lengths(size), data{data}, stride(stride)
{}

/**
* Creates a block_col_major accessor with a default stride
* (assumes no padding)
*
* @param data pointer to the block of memory containing the data
* @param lengths size / length of the accesses of each dimension
*/
constexpr GKO_ACC_ATTRIBUTES explicit block_col_major(length_type size,
data_type data)
: lengths(size),
data{data},
stride(helper::blk_col_major::default_stride_array(lengths))
{}

public:
/**
* Creates a block_col_major range which contains a read-only version of
* the current accessor.
*
* @returns a block column major range which is read-only.
*/
constexpr GKO_ACC_ATTRIBUTES range<const_accessor> to_const() const
{
// TODO Remove this functionality all together (if requested)
return range<const_accessor>(lengths, data, stride);
}

/**
* Returns the data element at the specified indices
*
* @param row row index
* @param col column index
*
* @return data element at (indices...)
*/
template <typename... Indices>
constexpr GKO_ACC_ATTRIBUTES
std::enable_if_t<are_all_integral<Indices...>::value, value_type &>
operator()(Indices &&... indices) const
{
return data[helper::blk_col_major::compute_index(
lengths, stride, std::forward<Indices>(indices)...)];
}

/**
* Returns the sub-range spanning the range (x1_span, x2_span, ...)
*
* @param rows row span
* @param cols column span
*
* @return sub-range spanning the given spans
*/
template <typename... SpanTypes>
constexpr GKO_ACC_ATTRIBUTES
std::enable_if_t<helper::are_index_span_compatible<SpanTypes...>::value,
range<block_col_major>>
operator()(SpanTypes... spans) const
{
return helper::validate_index_spans(lengths, spans...),
range<block_col_major>{
length_type{
(index_span{spans}.end - index_span{spans}.begin)...},
data + helper::blk_col_major::compute_index(
lengths, stride, (index_span{spans}.begin)...),
stride};
}

/**
* Returns the length in dimension `dimension`.
*
* @param dimension a dimension index
*
* @return length in dimension `dimension`
*/
constexpr GKO_ACC_ATTRIBUTES size_type length(size_type dimension) const
{
return lengths[dimension];
}

/**
* An array of dimension sizes.
*/
const length_type lengths;

/**
* Reference to the underlying data.
*/
const data_type data;

/**
* Distance between consecutive 'layers' for each dimension
* (except the second, for which it is 1).
*/
const stride_type stride;
};


} // namespace acc
} // namespace gko

#endif // GKO_ACCESSOR_BLOCK_COL_MAJOR_HPP_
137 changes: 137 additions & 0 deletions accessor/index_span.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*******************************<GINKGO LICENSE>******************************
Copyright (c) 2017-2021, the Ginkgo authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************<GINKGO LICENSE>*******************************/

#ifndef GKO_ACCESSOR_INDEX_SPAN_HPP_
#define GKO_ACCESSOR_INDEX_SPAN_HPP_

#include "utils.hpp"


namespace gko {
namespace acc {


/**
* An index_span is a lightweight structure used to describe a contiguous span
* of indices of one dimension.
*
* The main purpose of the index_span is to create sub-ranges from other ranges.
* An index_span `is` represents a contiguous set of indexes in one dimension of
* the range, starting from `is.begin` (inclusive) and ending at index `is.end`
* (exclusive). An index_span is only valid if its end is larger than its
* beginning.
*
* index_spans can be compared using `==` and `!=` operators. Two spans are
* equal iff both their `begin` and `end` values are identical.
*
* index_sets also have two distinct partial orders defined:
* 1. `x < y` (`y > x`) iff `x.end < y.begin`
* 2. `x <= y` (`y >= x`) iff `x.end <= y.begin`
* Note: `x < y || x == y` is not equivalent to `x <= y`.
*/
struct index_span {
/**
* Creates an index_span.
*
* @param begin the beginning (inclusive) of the index_span
* @param end the end (exclusive) of the index_span
*
*/
GKO_ACC_ATTRIBUTES constexpr index_span(size_type begin,
size_type end) noexcept
: begin{begin}, end{end}
{}

/**
* Creates an index_span representing the point `point`.
*
* The begin is set to `point`, and the end to `point + 1`
*
* @param point the point which the index_span represents
*/
GKO_ACC_ATTRIBUTES constexpr index_span(size_type point) noexcept
: index_span{point, point + 1}
{}

/**
* Checks if an index_span is valid.
*
* @returns true iff `this->begin < this->end`
*/
GKO_ACC_ATTRIBUTES constexpr bool is_valid() const { return begin < end; }

friend GKO_ACC_ATTRIBUTES constexpr bool operator<(const index_span &first,
const index_span &second)
{
return first.end < second.begin;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator<=(
const index_span &first, const index_span &second)
{
return first.end <= second.begin;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator>(const index_span &first,
const index_span &second)
{
return second < first;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator>=(
const index_span &first, const index_span &second)
{
return second <= first;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator==(
const index_span &first, const index_span &second)
{
return first.begin == second.begin && first.end == second.end;
}

friend GKO_ACC_ATTRIBUTES constexpr bool operator!=(
const index_span &first, const index_span &second)
{
return !(first == second);
}

const size_type begin;
const size_type end;
};


} // namespace acc
} // namespace gko


#endif // GKO_ACCESSOR_INDEX_SPAN_HPP_
Loading

0 comments on commit 3e31cc0

Please sign in to comment.