Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
libgluon/include/galois/cuda/DynamicBitset.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 /*
21  */
22 
29 // thread-safe dynamic bitset in CUDA
30 #pragma once
31 #include <cuda.h>
32 #include <math.h>
33 #include <iterator>
34 
41  size_t num_bits_capacity;
42  size_t num_bits;
43  uint64_t* bit_vector;
44 
45 public:
47  num_bits_capacity = 0;
48  num_bits = 0;
49  bit_vector = NULL;
50  }
51 
52  DynamicBitset(size_t nbits) { alloc(nbits); }
53 
55  if (bit_vector != NULL)
56  cudaFree(bit_vector);
57  }
58 
59  void alloc(size_t nbits) {
60  assert(num_bits == 0);
61  assert(sizeof(unsigned long long int) * 8 == 64);
62  assert(sizeof(uint64_t) * 8 == 64);
63  num_bits_capacity = nbits;
64  num_bits = nbits;
65  CUDA_SAFE_CALL(cudaMalloc(&bit_vector, vec_size() * sizeof(uint64_t)));
66  reset();
67  }
68 
69  void resize(size_t nbits) {
70  assert(nbits <= num_bits_capacity);
71  num_bits = nbits;
72  }
73 
74  __device__ __host__ size_t size() const { return num_bits; }
75 
76  __device__ __host__ size_t vec_size() const {
77  size_t bit_vector_size = (num_bits + 63) / 64;
78  return bit_vector_size;
79  }
80 
81  __device__ __host__ size_t alloc_size() const {
82  return vec_size() * sizeof(uint64_t);
83  }
84 
85  void reset() {
86  CUDA_SAFE_CALL(cudaMemset(bit_vector, 0, vec_size() * sizeof(uint64_t)));
87  }
88 
89  // assumes bit_vector is not updated (set) in parallel
90  __device__ bool test(const size_t id) const {
91  size_t bit_index = id / 64;
92  uint64_t bit_offset = 1;
93  bit_offset <<= (id % 64);
94  return ((bit_vector[bit_index] & bit_offset) != 0);
95  }
96 
97  __device__ void set(const size_t id) {
98  size_t bit_index = id / 64;
99  unsigned long long int bit_offset = 1;
100  bit_offset <<= (id % 64);
101  if ((bit_vector[bit_index] & bit_offset) == 0) { // test and set
102  atomicOr((unsigned long long int*)&bit_vector[bit_index], bit_offset);
103  }
104  }
105 
106  // different indices can be updated in parallel
107  __device__ void batch_reset(const size_t bit_index) {
108  bit_vector[bit_index] = 0;
109  }
110 
111  // different indices can be updated in parallel
112  // but assumes same index is not updated in parallel
113  __device__ void batch_bitwise_and(const size_t bit_index,
114  const uint64_t mask) {
115  bit_vector[bit_index] &= mask;
116  }
117 
118  void copy_to_cpu(uint64_t* bit_vector_cpu_copy) {
119  assert(bit_vector_cpu_copy != NULL);
120  CUDA_SAFE_CALL(cudaMemcpy(bit_vector_cpu_copy, bit_vector,
121  vec_size() * sizeof(uint64_t),
122  cudaMemcpyDeviceToHost));
123  }
124 
125  void copy_to_gpu(uint64_t* cpu_bit_vector) {
126  assert(cpu_bit_vector != NULL);
127  CUDA_SAFE_CALL(cudaMemcpy(bit_vector, cpu_bit_vector,
128  vec_size() * sizeof(uint64_t),
129  cudaMemcpyHostToDevice));
130  }
131 };
132 
134  : public std::iterator<std::random_access_iterator_tag, bool> {
135  DynamicBitset* bitset;
136  size_t offset;
137 
138 public:
139  __device__ __host__ __forceinline__ DynamicBitsetIterator(DynamicBitset* b,
140  size_t i = 0)
141  : bitset(b), offset(i) {}
142 
143  __device__ __host__ __forceinline__ DynamicBitsetIterator& operator++() {
144  offset++;
145  return *this;
146  }
147 
148  __device__ __host__ __forceinline__ DynamicBitsetIterator& operator--() {
149  offset--;
150  return *this;
151  }
152 
153  __device__ __host__ __forceinline__ bool
155  return (offset < bi.offset);
156  }
157 
158  __device__ __host__ __forceinline__ bool
160  return (offset <= bi.offset);
161  }
162 
163  __device__ __host__ __forceinline__ bool
165  return (offset > bi.offset);
166  }
167 
168  __device__ __host__ __forceinline__ bool
170  return (offset >= bi.offset);
171  }
172 
173  __device__ __host__ __forceinline__ DynamicBitsetIterator&
174  operator+=(size_t i) {
175  offset += i;
176  return *this;
177  }
178 
179  __device__ __host__ __forceinline__ DynamicBitsetIterator&
180  operator-=(size_t i) {
181  offset -= i;
182  return *this;
183  }
184 
185  __device__ __host__ __forceinline__ DynamicBitsetIterator
186  operator+(size_t i) {
187  return DynamicBitsetIterator(bitset, offset + i);
188  }
189 
190  __device__ __host__ __forceinline__ DynamicBitsetIterator
191  operator-(size_t i) {
192  return DynamicBitsetIterator(bitset, offset - i);
193  }
194 
195  __device__ __host__ __forceinline__ difference_type
197  return (offset - bi.offset);
198  }
199 
200  __device__ __forceinline__ bool operator*() const {
201  return bitset->test(offset);
202  }
203 
204  __device__ __forceinline__ bool operator[](const size_t id) const {
205  return bitset->test(offset + id);
206  }
207 };
208 
210  : public std::iterator<std::random_access_iterator_tag, size_t> {
211  size_t offset;
212 
213 public:
214  __device__ __host__ __forceinline__ IdentityIterator(size_t i = 0)
215  : offset(i) {}
216 
217  __device__ __host__ __forceinline__ IdentityIterator& operator++() {
218  offset++;
219  return *this;
220  }
221 
222  __device__ __host__ __forceinline__ IdentityIterator& operator--() {
223  offset--;
224  return *this;
225  }
226 
227  __device__ __host__ __forceinline__ bool
229  return (offset < bi.offset);
230  }
231 
232  __device__ __host__ __forceinline__ bool
234  return (offset <= bi.offset);
235  }
236 
237  __device__ __host__ __forceinline__ bool
239  return (offset > bi.offset);
240  }
241 
242  __device__ __host__ __forceinline__ bool
244  return (offset >= bi.offset);
245  }
246 
247  __device__ __host__ __forceinline__ IdentityIterator& operator+=(size_t i) {
248  offset += i;
249  return *this;
250  }
251 
252  __device__ __host__ __forceinline__ IdentityIterator& operator-=(size_t i) {
253  offset -= i;
254  return *this;
255  }
256 
257  __device__ __host__ __forceinline__ IdentityIterator operator+(size_t i) {
258  return IdentityIterator(offset + i);
259  }
260 
261  __device__ __host__ __forceinline__ IdentityIterator operator-(size_t i) {
262  return IdentityIterator(offset - i);
263  }
264 
265  __device__ __host__ __forceinline__ difference_type
267  return (offset - bi.offset);
268  }
269 
270  __device__ __forceinline__ size_t operator*() const { return offset; }
271 
272  __device__ __forceinline__ size_t operator[](const size_t id) const {
273  return offset + id;
274  }
275 };
__device__ __host__ __forceinline__ DynamicBitsetIterator(DynamicBitset *b, size_t i=0)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:139
__device__ __host__ __forceinline__ difference_type operator-(const IdentityIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:266
__device__ __host__ __forceinline__ bool operator>(const IdentityIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:238
__device__ bool test(const size_t id) const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:90
__device__ __host__ __forceinline__ bool operator>=(const IdentityIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:243
__device__ __host__ __forceinline__ bool operator>(const DynamicBitsetIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:164
__device__ __host__ size_t vec_size() const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:76
__device__ __host__ __forceinline__ IdentityIterator & operator++()
Definition: libgluon/include/galois/cuda/DynamicBitset.h:217
__device__ __host__ __forceinline__ IdentityIterator operator-(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:261
void alloc(size_t nbits)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:59
__device__ __host__ __forceinline__ DynamicBitsetIterator & operator+=(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:174
__device__ __host__ __forceinline__ DynamicBitsetIterator operator-(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:191
Dynamic Bitset, CUDA version.
Definition: libgluon/include/galois/cuda/DynamicBitset.h:40
DynamicBitset()
Definition: libgluon/include/galois/cuda/DynamicBitset.h:46
__device__ void batch_reset(const size_t bit_index)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:107
__device__ __host__ __forceinline__ DynamicBitsetIterator & operator-=(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:180
__device__ void set(const size_t id)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:97
__device__ __host__ __forceinline__ IdentityIterator operator+(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:257
__device__ __host__ size_t size() const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:74
__device__ __host__ __forceinline__ DynamicBitsetIterator & operator--()
Definition: libgluon/include/galois/cuda/DynamicBitset.h:148
void resize(size_t nbits)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:69
__device__ __forceinline__ size_t operator*() const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:270
~DynamicBitset()
Definition: libgluon/include/galois/cuda/DynamicBitset.h:54
void copy_to_cpu(uint64_t *bit_vector_cpu_copy)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:118
__device__ __host__ __forceinline__ bool operator<=(const IdentityIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:233
__device__ __host__ __forceinline__ difference_type operator-(const DynamicBitsetIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:196
__device__ __host__ __forceinline__ bool operator<(const DynamicBitsetIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:154
Definition: libgluon/include/galois/cuda/DynamicBitset.h:133
__device__ __host__ __forceinline__ DynamicBitsetIterator & operator++()
Definition: libgluon/include/galois/cuda/DynamicBitset.h:143
Definition: libgluon/include/galois/cuda/DynamicBitset.h:209
__device__ __host__ __forceinline__ IdentityIterator & operator-=(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:252
__device__ __host__ __forceinline__ IdentityIterator & operator+=(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:247
__device__ __host__ __forceinline__ IdentityIterator(size_t i=0)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:214
void copy_to_gpu(uint64_t *cpu_bit_vector)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:125
__device__ __host__ __forceinline__ IdentityIterator & operator--()
Definition: libgluon/include/galois/cuda/DynamicBitset.h:222
__device__ __forceinline__ bool operator[](const size_t id) const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:204
__device__ __host__ size_t alloc_size() const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:81
__device__ __host__ __forceinline__ bool operator<(const IdentityIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:228
__device__ __host__ __forceinline__ bool operator>=(const DynamicBitsetIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:169
__device__ __host__ __forceinline__ DynamicBitsetIterator operator+(size_t i)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:186
__device__ __forceinline__ bool operator*() const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:200
__device__ void batch_bitwise_and(const size_t bit_index, const uint64_t mask)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:113
__device__ __host__ __forceinline__ bool operator<=(const DynamicBitsetIterator &bi)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:159
DynamicBitset(size_t nbits)
Definition: libgluon/include/galois/cuda/DynamicBitset.h:52
__device__ __forceinline__ size_t operator[](const size_t id) const
Definition: libgluon/include/galois/cuda/DynamicBitset.h:272
void reset()
Definition: libgluon/include/galois/cuda/DynamicBitset.h:85