atlas
SVector.h
1 /*
2 * (C) Copyright 2013 ECMWF.
3 *
4 * This software is licensed under the terms of the Apache Licence Version 2.0
5 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6 * In applying this licence, ECMWF does not waive the privileges and immunities
7 * granted to it by virtue of its status as an intergovernmental organisation nor
8 * does it submit to any jurisdiction.
9 */
10 
11 #pragma once
12 
13 #include <algorithm>
14 #include <cassert>
15 #include <cstddef>
16 
17 #include "atlas/library/config.h"
18 #include "atlas/util/Allocate.h"
19 #ifndef __CUDA_ARCH__
20 #include "atlas/runtime/Exception.h"
21 #endif
22 
23 namespace atlas {
24 namespace array {
25 
26 //------------------------------------------------------------------------------
27 
28 template <typename T>
29 class SVector {
30 public:
31  ATLAS_HOST_DEVICE
32  SVector() : data_( nullptr ), size_( 0 ), externally_allocated_( false ) {}
33 
34  ATLAS_HOST_DEVICE
35  SVector( const T* data, const idx_t size ) : data_( data ), size_( size ), externally_allocated_( true ) {}
36 
37 #ifdef __CUDACC__
38  // Note that this does not copy!!! It is mainly intended to be passed to a CUDA kernel which requires value semantics for this class
39  ATLAS_HOST_DEVICE
40  SVector( SVector const& other ) : data_( other.data_ ), size_( other.size_ ), externally_allocated_( true ) {}
41 #endif
42 
43  ATLAS_HOST_DEVICE
44  SVector( SVector&& other ) :
45  data_( other.data_ ), size_( other.size_ ), externally_allocated_( other.externally_allocated_ ) {
46  other.data_ = nullptr;
47  other.size_ = 0;
48  other.externally_allocated_ = true;
49  }
50 
51  ATLAS_HOST_DEVICE
52  SVector& operator=( SVector&& other ) {
53  data_ = other.data_;
54  size_ = other.size_;
55  externally_allocated_ = other.externally_allocated_;
56  other.data_ = nullptr;
57  other.size_ = 0;
58  other.externally_allocated_ = true;
59  return *this;
60  }
61 
62  ATLAS_HOST_DEVICE
63  SVector( T* data, idx_t size ) : data_( data ), size_( size ), externally_allocated_( true ) {}
64 
65  SVector( idx_t N ) : data_( nullptr ), size_( N ), externally_allocated_( false ) { allocate( data_, N ); }
66 
67  ATLAS_HOST_DEVICE
68  ~SVector() { clear(); }
69 
70  ATLAS_HOST_DEVICE
71  void clear() {
72  if ( data_ && !externally_allocated_ ) {
73 #ifndef __CUDA_ARCH__
74  deallocate( data_, size_ );
75 #endif
76  }
77  data_ = nullptr;
78  size_ = 0;
79  externally_allocated_ = false;
80  }
81 
82  void insert( idx_t pos, idx_t dimsize ) {
83  T* data = nullptr;
84  allocate( data, size_ + dimsize );
85  for ( idx_t c = 0; c < pos; ++c ) {
86  data[c] = std::move( data_[c] );
87  }
88  for ( idx_t c = pos; c < size_; ++c ) {
89  data[c + dimsize] = std::move( data_[c] );
90  }
91  deallocate( data_, size_ );
92  data_ = data;
93  size_ += dimsize;
94  }
95 
96  size_t footprint() const { return sizeof( T ) * size_; }
97 
98  ATLAS_HOST_DEVICE
99  T* data() { return data_; }
100 
101  ATLAS_HOST_DEVICE
102  T const* data() const { return data_; }
103 
104  ATLAS_HOST_DEVICE
105  T& operator()( const idx_t idx ) {
106  assert( data_ && idx < size_ );
107  return data_[idx];
108  }
109  ATLAS_HOST_DEVICE
110  T const& operator()( const idx_t idx ) const {
111  assert( data_ && idx < size_ );
112  return data_[idx];
113  }
114 
115  ATLAS_HOST_DEVICE
116  T& operator[]( const idx_t idx ) {
117  assert( data_ && idx < size_ );
118  return data_[idx];
119  }
120  ATLAS_HOST_DEVICE
121  T const& operator[]( const idx_t idx ) const {
122  assert( data_ && idx < size_ );
123  return data_[idx];
124  }
125 
126  ATLAS_HOST_DEVICE
127  idx_t size() const { return size_; }
128 
129  void resize_impl( idx_t N ) {
130  if ( N == size_ )
131  return;
132 
133  T* d_ = nullptr;
134  allocate( d_, N );
135  for ( idx_t c = 0; c < std::min( size_, N ); ++c ) {
136  d_[c] = std::move( data_[c] );
137  }
138  deallocate( data_, size_ );
139  data_ = d_;
140  }
141 
142  void resize( idx_t N ) {
143 #ifndef __CUDA_ARCH__
144  ATLAS_ASSERT( not externally_allocated_, "Cannot resize externally allocated (or wrapped) data" );
145 #endif
146  resize_impl( N );
147  size_ = N;
148  }
149 
150 private:
151  static void allocate( T*& ptr, idx_t size ) {
152  if ( size > 0 ) {
153  util::allocate_managedmem( ptr, size );
154  for ( idx_t c = 0; c < size; ++c ) {
155  new ( ptr + c ) T();
156  }
157  }
158  }
159  static void deallocate( T*& ptr, idx_t size ) {
160  if ( ptr ) {
161  for ( idx_t c = 0; c < size; ++c ) {
162  ptr[c].~T();
163  }
164  util::delete_managedmem( ptr );
165  }
166  }
167 
168 private:
169  T* data_;
170  idx_t size_;
171  bool externally_allocated_;
172 };
173 
174 //------------------------------------------------------------------------------
175 
176 } // namespace array
177 } // namespace atlas
Definition: SVector.h:29
Contains all atlas classes and methods.
Definition: atlas-grids.cc:33
long idx_t
Integer type for indices in connectivity tables.
Definition: config.h:42