Files
cutlass/cutlass/zip_tile_iterator.h
Andrew Kerr 877bdcace6 Cutlass 1.3 Release (#42)
CUTLASS 1.3 Release
- Efficient GEMM kernel targeting Volta Tensor Cores via mma.sync instruction added in CUDA 10.1.
2019-03-20 10:49:17 -07:00

295 lines
10 KiB
C++

/***************************************************************************************************
* Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* * 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.
* * Neither the name of the NVIDIA CORPORATION 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 NVIDIA CORPORATION 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 TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************************************/
/*! \file
\brief Constructs an iterator that owns two tile iterator instances
*/
#pragma once
#include "cutlass/coord.h"
#include "cutlass/zip_tensor_ref.h"
#include "cutlass/zip_fragment.h"
#include "cutlass/util/pair.h"
namespace cutlass {
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Constructs an iterator from a pair of iterators
template <typename First_, typename Second_>
class ZipTileIterator {
public:
/// First iterator type
typedef First_ First;
/// Second iterator type
typedef Second_ Second;
///
typedef typename First::Scalar Scalar;
/// Params object
struct Params {
/// Parameters of first iterator
typename First::Params first;
/// Parameters of second iterator
typename Second::Params second;
/// Constructs a parameters object
CUTLASS_HOST_DEVICE
Params() {}
/// Constructs a parameters object
CUTLASS_HOST_DEVICE
Params(typename First::Params const &_first, typename Second::Params const &_second)
: first(_first), second(_second) {}
};
/// Fragment type
typedef ZipFragment<typename First::Fragment, typename Second::Fragment> Fragment;
/// Predicate vector
typedef typename First::PredicateVector PredicateVector;
/// Index type
typedef platform::Pair<typename First::Index, typename Second::Index> Index;
/// Long index type
typedef platform::Pair<typename First::LongIndex, typename Second::LongIndex> LongIndex;
/// Tensor reference
typedef ZipTensorRef<
typename First::TensorRef,
typename Second::TensorRef> TensorRef;
//
// Data members
//
/// First iterator
First first;
/// Second iterator
Second second;
//
// Methods
//
/// Default constructor
CUTLASS_DEVICE
ZipTileIterator() {}
/// Constructs a zip iterator from params
CUTLASS_DEVICE
ZipTileIterator(Params const &_params, Coord<3> const &threadblock_offset = make_Coord(0, 0, 0))
: first(_params.first, threadblock_offset), second(_params.second, threadblock_offset) {}
/// Constructs a zip iterator from iterator instances
CUTLASS_DEVICE
ZipTileIterator(First const &_first, Second const &_second) : first(_first), second(_second) {}
/// Constructs a zip iterator from iterator instances
CUTLASS_DEVICE
ZipTileIterator(TensorRef const &ref) : first(ref.first), second(ref.second) {}
/// Constructs a zip iterator from iterator instances
CUTLASS_DEVICE
ZipTileIterator(Params const &_params, TensorRef const &ref):
first(_params.first, ref.first), second(_params.second, ref.second) {}
//
// Predicate initialization
//
/// Initializes a predicate vector using a RegularTilePredicateFunctor
template <
/// Predicate iterator
typename PredicateIterator>
CUTLASS_HOST_DEVICE void initialize_predicates(PredicateIterator predicate_it,
Coord<3> const &bounds,
Coord<3> const &block_offset = make_Coord(0,
0,
0)) {
first.initialize_predicates(predicate_it, bounds, block_offset);
}
/// Initializes a predicate vector using an arbitrary predicate functor
template <
/// Predicate iterator
typename PredicateIterator,
/// Functor computing predicates
typename PredicateFunctor>
CUTLASS_HOST_DEVICE void initialize_predicates(PredicateIterator predicate_it,
PredicateFunctor const &functor,
Coord<3> const &block_offset) {
first.initialize_predicates(predicate_it, functor, block_offset);
}
//
// No predicates
//
/// Loads a fragment and increments without predicates
template <typename Fragment>
CUTLASS_DEVICE void load_post_increment(Fragment &fragment) {
first.load_post_increment(fragment.first);
second.load_post_increment(fragment.second);
}
/// Loads a fragment and increments without predicates
template <typename Fragment>
CUTLASS_DEVICE void load_post_increment(Fragment &fragment,
Coord<4> const &offset) {
first.load_post_increment(fragment.first, offset);
second.load_post_increment(fragment.second, offset);
}
/// Loads a fragment without predicates
template <typename Fragment>
CUTLASS_DEVICE void load(Fragment &fragment) const {
first.load(fragment.first);
second.load(fragment.second);
}
/// Loads a fragment without predicates
template <typename Fragment>
CUTLASS_DEVICE void load(Fragment &fragment,
Coord<4> const &offset) const {
first.load(fragment.first, offset);
second.load(fragment.second, offset);
}
/// Stores a fragment and increments without predicates
template <typename Fragment>
CUTLASS_DEVICE void store_post_increment(Fragment const &fragment) {
first.store_post_increment(fragment.first);
second.store_post_increment(fragment.second);
}
/// Stores a fragment and increments without predicates
template <typename Fragment>
CUTLASS_DEVICE void store_post_increment(Fragment const &fragment,
Coord<4> const &offset) {
first.store_post_increment(fragment.first, offset);
second.store_post_increment(fragment.second, offset);
}
/// Stores a fragment without predicates
template <typename Fragment>
CUTLASS_DEVICE void store(Fragment const &fragment) const {
first.store(fragment.first);
second.store(fragment.second);
}
/// Stores a fragment without predicates
template <typename Fragment>
CUTLASS_DEVICE void store(Fragment const &fragment,
Coord<4> const &offset) const {
first.store(fragment.first, offset);
second.store(fragment.second, offset);
}
//
// With predication
//
/// Loads a fragment and increments, using predicates
template <typename Fragment, typename PredicateIterator>
CUTLASS_DEVICE void load_post_increment(Fragment &fragment, PredicateIterator pred_it) {
first.load_post_increment(fragment.first, pred_it);
second.load_post_increment(fragment.second, pred_it);
}
/// Loads a fragment with predicates
template <typename Fragment, typename PredicateIterator>
CUTLASS_DEVICE void load(Fragment &fragment, PredicateIterator pred_it) const {
first.load(fragment.first, pred_it);
second.load(fragment.second, pred_it);
}
/// Loads a fragment and increments, using predicates
template <typename Fragment, typename PredicateIterator>
CUTLASS_DEVICE void store_post_increment(Fragment const &fragment, PredicateIterator pred_it) {
first.store_post_increment(fragment.first, pred_it);
second.store_post_increment(fragment.second, pred_it);
}
/// Loads a fragment with predicates
template <typename Fragment, typename PredicateIterator>
CUTLASS_DEVICE void store(Fragment const &fragment, PredicateIterator pred_it) const {
first.store(fragment.first, pred_it);
second.store(fragment.second, pred_it);
}
//
// Advances the iterators
//
/// Increments store iterator to next tile
CUTLASS_DEVICE ZipTileIterator &increment(int count = 1) {
first.increment(count);
second.increment(count);
return *this;
}
/// Increments to next tile
CUTLASS_DEVICE ZipTileIterator &operator++() { return increment(); }
CUTLASS_DEVICE ZipTileIterator &operator+=(int count) { return increment(count); }
/// Adds a vector offset to the underlying iterators
CUTLASS_DEVICE ZipTileIterator &operator+=(Coord<3> const &offset) {
first += offset;
second += offset;
return *this;
}
/// Increments store iterator to previous tile
CUTLASS_DEVICE ZipTileIterator &decrement(int count = 1) {
first.decrement(count);
second.decrement(count);
return *this;
}
/// Increments to subsequent tile
CUTLASS_DEVICE ZipTileIterator &operator--() { return decrement(); }
/// Decrements to previous tile
CUTLASS_DEVICE ZipTileIterator &operator-=(int count) { return decrement(count); }
/// Adds an offset to both iterators
CUTLASS_DEVICE void add_pointer_offset(LongIndex offset) {
first.add_pointer_offset(offset.first);
second.add_pointer_offset(offset.second);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
} // namspace cutlass