1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
#ifndef HeterogeneousCore_AlpakaInterface_interface_SimpleVector_h
#define HeterogeneousCore_AlpakaInterface_interface_SimpleVector_h
// author: Felice Pantaleo, CERN, 2018
// alpaka integration in cmssw: Adriano Di Florio, 2022
#include <type_traits>
#include <utility>
#include <alpaka/alpaka.hpp>
namespace cms::alpakatools {
template <class T>
struct SimpleVector {
constexpr SimpleVector() = default;
// ownership of m_data stays within the caller
constexpr void construct(int capacity, T *data) {
m_size = 0;
m_capacity = capacity;
m_data = data;
}
constexpr int push_back_unsafe(const T &element) {
auto previousSize = m_size;
m_size++;
if (previousSize < m_capacity) {
m_data[previousSize] = element;
return previousSize;
} else {
--m_size;
return -1;
}
}
template <class... Ts>
constexpr int emplace_back_unsafe(Ts &&...args) {
auto previousSize = m_size;
m_size++;
if (previousSize < m_capacity) {
(new (&m_data[previousSize]) T(std::forward<Ts>(args)...));
return previousSize;
} else {
--m_size;
return -1;
}
}
ALPAKA_FN_ACC inline T &back() { return m_data[m_size - 1]; }
ALPAKA_FN_ACC inline const T &back() const {
if (m_size > 0) {
return m_data[m_size - 1];
} else
return T(); //undefined behaviour
}
// thread-safe version of the vector, when used in a CUDA kernel
template <typename TAcc>
ALPAKA_FN_ACC int push_back(const TAcc &acc, const T &element) {
auto previousSize = alpaka::atomicAdd(acc, &m_size, 1, alpaka::hierarchy::Blocks{});
if (previousSize < m_capacity) {
m_data[previousSize] = element;
return previousSize;
} else {
alpaka::atomicSub(acc, &m_size, 1, alpaka::hierarchy::Blocks{});
return -1;
}
}
template <typename TAcc, class... Ts>
ALPAKA_FN_ACC int emplace_back(const TAcc &acc, Ts &&...args) {
auto previousSize = alpaka::atomicAdd(acc, &m_size, 1, alpaka::hierarchy::Blocks{});
if (previousSize < m_capacity) {
(new (&m_data[previousSize]) T(std::forward<Ts>(args)...));
return previousSize;
} else {
alpaka::atomicSub(acc, &m_size, 1, alpaka::hierarchy::Blocks{});
return -1;
}
}
// thread safe version of resize
template <typename TAcc>
ALPAKA_FN_ACC int extend(const TAcc &acc, int size = 1) {
auto previousSize = alpaka::atomicAdd(acc, &m_size, size, alpaka::hierarchy::Blocks{});
if (previousSize < m_capacity) {
return previousSize;
} else {
alpaka::atomicSub(acc, &m_size, size, alpaka::hierarchy::Blocks{});
return -1;
}
}
template <typename TAcc>
ALPAKA_FN_ACC int shrink(const TAcc &acc, int size = 1) {
auto previousSize = alpaka::atomicSub(acc, &m_size, size, alpaka::hierarchy::Blocks{});
if (previousSize >= size) {
return previousSize - size;
} else {
alpaka::atomicAdd(acc, &m_size, size, alpaka::hierarchy::Blocks{});
return -1;
}
}
inline constexpr bool empty() const { return m_size <= 0; }
inline constexpr bool full() const { return m_size >= m_capacity; }
inline constexpr T &operator[](int i) { return m_data[i]; }
inline constexpr const T &operator[](int i) const { return m_data[i]; }
inline constexpr void reset() { m_size = 0; }
inline constexpr int size() const { return m_size; }
inline constexpr int capacity() const { return m_capacity; }
inline constexpr T const *data() const { return m_data; }
inline constexpr void resize(int size) { m_size = size; }
inline constexpr void set_data(T *data) { m_data = data; }
private:
int m_size;
int m_capacity;
T *m_data;
};
// ownership of m_data stays within the caller
template <class T>
SimpleVector<T> make_SimpleVector(int capacity, T *data) {
SimpleVector<T> ret;
ret.construct(capacity, data);
return ret;
}
// ownership of m_data stays within the caller
template <class T>
SimpleVector<T> *make_SimpleVector(SimpleVector<T> *mem, int capacity, T *data) {
auto ret = new (mem) SimpleVector<T>();
ret->construct(capacity, data);
return ret;
}
} // namespace cms::alpakatools
#endif // AlpakaCore_SimpleVector_h
|