15 #include <cuda_runtime.h>
16 #include <initializer_list>
22 namespace faiss {
namespace gpu {
29 template <
typename U>
class PtrTraits>
34 template <
typename TensorType,
36 template <
typename U>
class PtrTraits>
44 typedef T* __restrict__ PtrType;
75 typename IndexT = int,
79 enum { NumDim = Dim };
81 typedef IndexT IndexType;
82 enum { IsContig = Contig };
83 typedef typename PtrTraits<T>::PtrType DataPtrType;
84 typedef Tensor<T, Dim, Contig, IndexT, PtrTraits> TensorType;
87 __host__ __device__
Tensor();
90 __host__ __device__
Tensor(Tensor<T, Dim, Contig, IndexT, PtrTraits>& t)
94 __host__ __device__
Tensor(Tensor<T, Dim, Contig, IndexT, PtrTraits>&& t)
98 __host__ __device__ Tensor<T, Dim, Contig, IndexT, PtrTraits>&
99 operator=(Tensor<T, Dim, Contig, IndexT, PtrTraits>& t) =
default;
102 __host__ __device__ Tensor<T, Dim, Contig, IndexT, PtrTraits>&
103 operator=(Tensor<T, Dim, Contig, IndexT, PtrTraits>&& t);
107 const IndexT
sizes[Dim]);
109 std::initializer_list<IndexT>
sizes);
115 const IndexT
sizes[Dim],
119 __host__
void copyFrom(Tensor<T, Dim, Contig, IndexT, PtrTraits>& t,
120 cudaStream_t stream);
123 __host__
void copyTo(Tensor<T, Dim, Contig, IndexT, PtrTraits>& t,
124 cudaStream_t stream);
128 template <
int OtherDim>
129 __host__ __device__
bool
130 isSame(
const Tensor<T, OtherDim, Contig, IndexT, PtrTraits>& rhs)
const;
134 template <
typename U>
135 __host__ __device__ Tensor<U, Dim, Contig, IndexT, PtrTraits>
cast();
138 template <
typename U>
140 const Tensor<U, Dim, Contig, IndexT, PtrTraits>
cast()
const;
148 template <
typename U>
149 __host__ __device__ Tensor<U, Dim, Contig, IndexT, PtrTraits>
castResize();
152 template <
typename U>
153 __host__ __device__
const Tensor<U, Dim, Contig, IndexT, PtrTraits>
157 template <
typename U>
163 template <
typename NewIndexT>
164 __host__ Tensor<T, Dim, Contig, NewIndexT, PtrTraits>
169 template <
typename NewIndexT>
173 __host__ __device__
inline DataPtrType
data() {
179 __host__ __device__
inline DataPtrType
end() {
184 __host__ __device__
inline
185 const DataPtrType
data()
const {
191 __host__ __device__
inline DataPtrType
end()
const {
196 template <
typename U>
197 __host__ __device__
inline
198 typename PtrTraits<U>::PtrType
dataAs() {
199 return reinterpret_cast<typename PtrTraits<U>::PtrType
>(
data_);
203 template <
typename U>
204 __host__ __device__
inline
205 const typename PtrTraits<const U>::PtrType
dataAs()
const {
206 return reinterpret_cast<typename PtrTraits<const U>::PtrType
>(
data_);
210 __host__ __device__
inline
215 __host__ __device__
inline
221 __host__ __device__
inline IndexT
getSize(
int i)
const {
227 __host__ __device__
inline IndexT
getStride(
int i)
const {
242 __host__ __device__
inline const IndexT*
sizes()
const {
247 __host__ __device__
inline const IndexT*
strides()
const {
262 __host__ __device__
bool isConsistentlySized(
int i)
const;
267 __host__ __device__
bool isConsistentlySized()
const;
282 template <
int NewDim>
289 template <
int NewDim>
296 template <
int NewDim>
303 template <
int NewDim>
309 template <
int SubDim>
311 view(DataPtrType at);
315 template <
int SubDim>
331 narrow(
int dim, IndexT start, IndexT size);
336 template <
int NewDim>
338 view(std::initializer_list<IndexT>
sizes);
354 template <
typename IndexType>
355 bool canCastIndexType() {
359 template <
typename IndexType,
typename T,
typename... U>
360 bool canCastIndexType(
const T& arg,
const U&... args) {
361 return arg.canCastIndexType<IndexType>() &&
362 canCastIndexType(args...);
367 template <
typename IndexType,
typename... T>
368 bool canCastIndexType(
const T&... args) {
369 return detail::canCastIndexType(args...);
375 template <
typename TensorType,
template <
typename U>
class PtrTraits>
379 operator=(
typename TensorType::DataType val) {
385 __host__ __device__
operator typename TensorType::DataType&() {
390 __host__ __device__
operator const typename TensorType::DataType&()
const {
395 __host__ __device__
typename TensorType::DataType* operator&() {
400 __host__ __device__
const typename TensorType::DataType* operator&()
const {
405 __host__ __device__
inline typename TensorType::DataPtrType
data() {
410 __host__ __device__
inline
411 const typename TensorType::DataPtrType
data()
const {
416 template <
typename T>
417 __host__ __device__ T&
as() {
422 template <
typename T>
423 __host__ __device__
const T&
as()
const {
428 template <
typename T>
429 __host__ __device__
inline
430 typename PtrTraits<T>::PtrType
dataAs() {
431 return reinterpret_cast<typename PtrTraits<T>::PtrType
>(
data_);
435 template <
typename T>
436 __host__ __device__
inline
437 typename PtrTraits<const T>::PtrType
dataAs()
const {
438 return reinterpret_cast<typename PtrTraits<const T>::PtrType
>(
data_);
442 __device__
inline typename TensorType::DataType
ldg()
const {
443 #if __CUDA_ARCH__ >= 350
451 template <
typename T>
453 #if __CUDA_ARCH__ >= 350
454 return __ldg(dataAs<T>());
465 friend class Tensor<typename TensorType::DataType,
467 TensorType::IsContig,
468 typename TensorType::IndexType,
473 typename TensorType::DataPtrType data)
482 typename TensorType::DataPtrType
const data_;
486 template <
typename TensorType,
488 template <
typename U>
class PtrTraits>
493 __host__ __device__
inline
494 SubTensor<TensorType, SubDim - 1, PtrTraits>
496 if (TensorType::IsContig && SubDim == 1) {
498 return SubTensor<TensorType, SubDim - 1, PtrTraits>(
501 return SubTensor<TensorType, SubDim - 1, PtrTraits>(
503 data_ + index * tensor_.getStride(TensorType::NumDim - SubDim));
509 __host__ __device__
inline
510 const SubTensor<TensorType, SubDim - 1, PtrTraits>
512 if (TensorType::IsContig && SubDim == 1) {
514 return SubTensor<TensorType, SubDim - 1, PtrTraits>(
517 return SubTensor<TensorType, SubDim - 1, PtrTraits>(
519 data_ + index * tensor_.getStride(TensorType::NumDim - SubDim));
524 __host__ __device__
typename TensorType::DataType* operator&() {
529 __host__ __device__
const typename TensorType::DataType* operator&()
const {
534 __host__ __device__
inline typename TensorType::DataPtrType
data() {
539 __host__ __device__
inline
540 const typename TensorType::DataPtrType
data()
const {
545 template <
typename T>
546 __host__ __device__ T&
as() {
551 template <
typename T>
552 __host__ __device__
const T&
as()
const {
557 template <
typename T>
558 __host__ __device__
inline
559 typename PtrTraits<T>::PtrType
dataAs() {
560 return reinterpret_cast<typename PtrTraits<T>::PtrType
>(
data_);
564 template <
typename T>
565 __host__ __device__
inline
566 typename PtrTraits<const T>::PtrType
dataAs()
const {
567 return reinterpret_cast<typename PtrTraits<const T>::PtrType
>(
data_);
571 __device__
inline typename TensorType::DataType
ldg()
const {
572 #if __CUDA_ARCH__ >= 350
580 template <
typename T>
582 #if __CUDA_ARCH__ >= 350
583 return __ldg(dataAs<T>());
591 Tensor<
typename TensorType::DataType,
593 TensorType::IsContig,
594 typename TensorType::IndexType,
601 friend class SubTensor<TensorType, SubDim + 1, PtrTraits>;
605 Tensor<
typename TensorType::DataType,
607 TensorType::IsContig,
608 typename TensorType::IndexType,
613 typename TensorType::DataPtrType
data)
622 typename TensorType::DataPtrType
const data_;
627 template <
typename T,
int Dim,
bool Contig,
628 typename IndexT,
template <
typename U>
class PtrTraits>
629 __host__ __device__
inline
635 *
this, data_)[index]);
638 template <
typename T,
int Dim,
bool Contig,
639 typename IndexT,
template <
typename U>
class PtrTraits>
640 __host__ __device__
inline
646 const_cast<TensorType&
>(*this), data_)[index]);
651 #include "Tensor-inl.cuh"
__host__ __device__ Tensor()
Default constructor.
__host__ __device__ const PtrTraits< const U >::PtrType dataAs() const
Cast to a different datatype.
__host__ __device__ Tensor< T, NewDim, Contig, IndexT, PtrTraits > downcastInner()
__host__ __device__ PtrTraits< const T >::PtrType dataAs() const
Cast to a different datatype (const)
__host__ __device__ bool isContiguousDim(int i) const
Returns true if the given dimension index has no padding.
__device__ T ldgAs() const
Use the texture cache for reads; cast as a particular type.
__host__ __device__ Tensor< T, Dim, Contig, IndexT, PtrTraits > transpose(int dim1, int dim2) const
__host__ __device__ DataPtrType data()
Returns a raw pointer to the start of our data.
__host__ __device__ PtrTraits< T >::PtrType dataAs()
Cast to a different datatype.
__host__ __device__ Tensor< T, Dim, Contig, IndexT, PtrTraits > narrowOutermost(IndexT start, IndexT size)
__host__ __device__ PtrTraits< const T >::PtrType dataAs() const
Cast to a different datatype (const)
DataPtrType data_
Raw pointer to where the tensor data begins.
__host__ __device__ Tensor< T, Dim, Contig, IndexT, PtrTraits > & operator=(Tensor< T, Dim, Contig, IndexT, PtrTraits > &t)=default
Assignment.
__host__ __device__ const TensorType::DataPtrType data() const
Returns a raw accessor to our slice (const).
__device__ TensorType::DataType ldg() const
Use the texture cache for reads.
__host__ __device__ Tensor< T, NewDim, Contig, IndexT, PtrTraits > upcastOuter()
__host__ bool canCastIndexType() const
__host__ __device__ T & as()
Cast to a different datatype.
__host__ __device__ T & as()
Cast to a different datatype.
TensorType & tensor_
The tensor we're referencing.
__host__ __device__ Tensor< T, Dim, false, IndexT, PtrTraits > narrow(int dim, IndexT start, IndexT size)
__device__ TensorType::DataType ldg() const
Use the texture cache for reads.
__host__ __device__ Tensor< U, Dim, Contig, IndexT, PtrTraits > cast()
__host__ void copyTo(Tensor< T, Dim, Contig, IndexT, PtrTraits > &t, cudaStream_t stream)
Copies ourselves into a tensor; sizes must match.
TensorType::DataPtrType const data_
The start of our sub-region.
__host__ __device__ bool isSame(const Tensor< T, OtherDim, Contig, IndexT, PtrTraits > &rhs) const
__host__ Tensor< T, Dim, Contig, NewIndexT, PtrTraits > castIndexType() const
__host__ __device__ IndexT numElements() const
__device__ T ldgAs() const
Use the texture cache for reads; cast as a particular type.
__host__ __device__ const SubTensor< TensorType, SubDim-1, PtrTraits > operator[](typename TensorType::IndexType index) const
Tensor< typename TensorType::DataType, SubDim, TensorType::IsContig, typename TensorType::IndexType, PtrTraits > view()
TensorType::DataPtrType const data_
Where our value is located.
__host__ __device__ const IndexT * strides() const
Returns the stride array.
__host__ __device__ IndexT getStride(int i) const
__host__ __device__ const IndexT * sizes() const
Returns the size array.
__host__ __device__ PtrTraits< U >::PtrType dataAs()
Cast to a different datatype.
__host__ __device__ size_t getSizeInBytes() const
__host__ __device__ DataPtrType end()
Specialization for a view of a single value (0-dimensional)
__host__ __device__ Tensor< T, NewDim, Contig, IndexT, PtrTraits > upcastInner()
__host__ __device__ Tensor< T, SubDim, Contig, IndexT, PtrTraits > view()
TensorType & tensor_
The tensor we're referencing.
__host__ __device__ DataPtrType end() const
__host__ __device__ const TensorType::DataPtrType data() const
Returns a raw accessor to our slice (const).
__host__ __device__ SubTensor< TensorType, SubDim-1, PtrTraits > operator[](typename TensorType::IndexType index)
__host__ __device__ IndexT getSize(int i) const
__host__ void copyFrom(Tensor< T, Dim, Contig, IndexT, PtrTraits > &t, cudaStream_t stream)
Copies a tensor into ourselves; sizes must match.
__host__ __device__ const T & as() const
Cast to a different datatype (const).
A SubDim-rank slice of a parent Tensor.
__host__ __device__ PtrTraits< T >::PtrType dataAs()
Cast to a different datatype.
__host__ __device__ TensorType::DataPtrType data()
Returns a raw accessor to our slice.
IndexT stride_[Dim]
Array of strides (in sizeof(T) terms) per each dimension.
__host__ __device__ bool isContiguous() const
__host__ __device__ Tensor< T, NewDim, Contig, IndexT, PtrTraits > downcastOuter()
IndexT size_[Dim]
Size per each dimension.
__host__ __device__ TensorType::DataPtrType data()
Returns a raw accessor to our slice.
__host__ __device__ detail::SubTensor< TensorType, Dim-1, PtrTraits > operator[](IndexT)
Returns a read/write view of a portion of our tensor.
__host__ __device__ bool canCastResize() const
Returns true if we can castResize() this tensor to the new type.
__host__ __device__ const T & as() const
Cast to a different datatype (const).
__host__ __device__ const DataPtrType data() const
Returns a raw pointer to the start of our data (const).
__host__ __device__ Tensor< U, Dim, Contig, IndexT, PtrTraits > castResize()