Skip to content

Commit 688037a

Browse files
committed
finally finished gpu support git add .!
1 parent e61303c commit 688037a

6 files changed

Lines changed: 50 additions & 33 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ To compile it with __Openmp__ and enable Offlowding to GPUs, you will need to us
2020

2121
All arithmetic operations, self-operators, and comparisons excluding `==, !=` (for performance reasons) are now supported on GPUs.
2222

23-
Operation requiring xor reduction on single bytes (currently only __multiplication between a `Matrix` and a `Vector`__) have a performance disadvantage on GPUs because atomic xor for type `uint8_t` is not supported by Openmp on GPU (see [issue #1](https://github.com/jolatechno/binary_algebra/issues/1)), and so the use of `omp critical` was required which is a huge performance hit compared to `omp atomic`.
23+
Atomic operations for type `uint8_t` are not supported by __Openmp__ on GPU (see [issue #1](https://github.com/jolatechno/binary_algebra/issues/1)). I finally found a work around for every operation, either by converting types, or by grouping operations together to only apply atomic operations on `long unsigned int`.
2424

25-
I will implement threshold for which will redirect operation to the CPU without Opnemp, the CPU with Openmp, or GPUs; according to the size of the `Matrix` or `Vector`.
25+
I will implement threshold for which will redirect operation to the CPU without __Openmp__, the CPU with __Openmp__, or GPUs; according to the size of the `Matrix` or `Vector`.
2626

2727
## What is "binary algebra" ?
2828

src/arithmetic.inl

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ Matrix Matrix::operator*(Matrix const& other) const {
232232
for (j = 0; j < _size; j++)
233233
for (k = 0; k < _width; k++)
234234
for (i = 0; i < _height; i++) {
235-
#pragma omp atomic
235+
_OPENMP_PRAGMA("omp atomic")
236236
res_blocks[i + j*_height] ^= multiply_block_block(this_blocks[k + j*_width], other_blocks[i + k*_size]);
237237
}
238238

@@ -244,17 +244,27 @@ Vector Matrix::operator*(Vector const& other) const {
244244

245245
Vector res(height);
246246

247-
int16_t _width = width;
248-
int16_t _height = height;
247+
auto _width = width;
248+
auto _height = height;
249249

250-
ARITHMETIC_VARIABLE_HEADER;
250+
long unsigned int *res_blocks = (long unsigned int*)res.blocks;
251+
uint8_t *other_blocks = other.blocks;
252+
uint64_t *this_blocks = blocks;
251253

252254
int16_t i, k;
253255
_OPENMP_GPU_PRAGMA("omp parallel for collapse(2) schedule(static) shared(other_blocks, res_blocks, this_blocks)", \
254256
"omp target teams distribute parallel for collapse(2) map(to:this_blocks[:_width * _height], other_blocks[:_width]) map(from:res_blocks[:_height])")
255257
for (k = 0; k < _width; k++)
256-
for (i = 0; i < _height; i++)
257-
utils->_atomic_xor_fetch_8(res_blocks[i], multiply_block_byte(this_blocks[k + i*_width], other_blocks[k]));
258+
for (i = 0; i < _height/8; i++) {
259+
_OPENMP_PRAGMA("omp atomic")
260+
res_blocks[i] ^= multiply_block_word(this_blocks[k + 8*i*_width], this_blocks[k + (8*i + 1)*_width], this_blocks[k + (8*i + 2)*_width], this_blocks[k + (8*i + 3)*_width], \
261+
this_blocks[k + (8*i + 4)*_width], this_blocks[k + (8*i + 5)*_width], this_blocks[k + (8*i + 6)*_width], this_blocks[k + (8*i + 7)*_width], \
262+
other_blocks[k]);
263+
}
264+
265+
for (k = 0; k < _width; k++)
266+
for (i = _height - _height%8; i < _height; i++)
267+
res.blocks[i] ^= multiply_block_byte(this_blocks[k + i*_width], other_blocks[k]);
258268

259269
return res;
260270
}

src/binary_arithmetic.hpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@ class Matrix {
2222
Utils* utils;
2323

2424
//block operations
25-
#if defined(_OPENMP) && defined(TARGET)
26-
#pragma omp declare target
27-
#endif
25+
_OPENMP_GPU("omp declare target")
2826
inline uint64_t transpose_block(uint64_t block) const;
2927
inline uint8_t multiply_block_byte(uint64_t block, uint8_t vect) const;
28+
inline uint64_t multiply_block_word(uint64_t block0, uint64_t block1, uint64_t block2, uint64_t block3, \
29+
uint64_t block4, uint64_t block5, uint64_t block6, uint64_t block7, \
30+
uint8_t vect) const;
3031
inline uint64_t multiply_block_block(uint64_t block_left, uint64_t block_right) const;
31-
#if defined(_OPENMP) && defined(TARGET)
32-
#pragma omp end declare target
33-
#endif
32+
_OPENMP_GPU("omp end declare target")
3433

3534
//for comparaisons
3635
int difference(Matrix const& mat) const;
@@ -117,13 +116,9 @@ class Vector {
117116
Utils* utils;
118117

119118
//block operations
120-
#if defined(_OPENMP) && defined(TARGET)
121-
#pragma omp declare target
122-
#endif
119+
_OPENMP_GPU("omp declare target")
123120
inline uint64_t multiply_byte_byte(uint8_t vect_left, uint8_t vect_right) const;
124-
#if defined(_OPENMP) && defined(TARGET)
125-
#pragma omp end declare target
126-
#endif
121+
_OPENMP_GPU("omp end declare target")
127122

128123
//for comparaisons
129124
int difference(Vector const& vect) const;

src/openmp.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,12 @@
1515
#define _OPENMP_GPU_PRAGMA(cpu, gpu)
1616

1717
#endif
18+
19+
#if defined(_OPENMP) && defined(TARGET)
20+
#define _OPENMP_GPU(gpu) _Pragma(gpu)
21+
22+
#else
23+
#define _OPENMP_GPU(gpu)
24+
25+
#endif
1826
#endif

src/utils/block_arithmetic.inl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ inline uint8_t Matrix::multiply_block_byte(uint64_t block, uint8_t vect) const
3939
return sum;
4040
}
4141

42+
inline uint64_t Matrix::multiply_block_word(uint64_t block0, uint64_t block1, uint64_t block2, uint64_t block3, \
43+
uint64_t block4, uint64_t block5, uint64_t block6, uint64_t block7, \
44+
uint8_t vect) const {
45+
uint64_t res = multiply_block_byte(block7, vect);
46+
res = (res << 8) | multiply_block_byte(block6, vect);
47+
res = (res << 8) | multiply_block_byte(block5, vect);
48+
res = (res << 8) | multiply_block_byte(block4, vect);
49+
res = (res << 8) | multiply_block_byte(block3, vect);
50+
res = (res << 8) | multiply_block_byte(block2, vect);
51+
res = (res << 8) | multiply_block_byte(block1, vect);
52+
53+
return (res << 8) | multiply_block_byte(block0, vect);
54+
}
55+
4256
inline uint64_t Matrix::multiply_block_block(uint64_t block_left, uint64_t block_right) const { //changed to acomodate the switch in block indices, check the readme
4357
uint64_t res = 0;
4458
//uint64_t block_right_t = transpose_block(block_right);
@@ -49,6 +63,7 @@ inline uint64_t Matrix::multiply_block_block(uint64_t block_left, uint64_t bloc
4963
return res;
5064
}
5165

66+
5267
inline uint64_t Vector::multiply_byte_byte(uint8_t vect_left, uint8_t vect_right) const { //changed to acomodate the switch in block indices, check the readme
5368
uint64_t res = 0;
5469

src/utils/utils.hpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,12 @@ class Utils {
1212
friend class Matrix;
1313

1414
private:
15-
#if defined(_OPENMP) && defined(TARGET)
16-
#pragma omp declare target
17-
#endif
15+
_OPENMP_GPU("omp declare target")
1816
static inline bool bit_out_of_byte_reversed(uint8_t byte, uint8_t bit);
1917
static inline uint8_t byte_out_of_word_reversed(uint64_t word, uint8_t byte);
2018
static inline int count_ones_8(uint8_t byte);
2119
static inline int count_ones_64(uint64_t word);
22-
23-
static inline void _atomic_xor_fetch_8(uint8_t &x1, uint8_t x2); //because openmp dosen't implement it on GPUs
24-
#if defined(_OPENMP) && defined(TARGET)
25-
#pragma omp end declare target
26-
#endif
20+
_OPENMP_GPU("omp end declare target")
2721
};
2822

2923
inline bool Utils::bit_out_of_byte_reversed(uint8_t byte, uint8_t bit) {
@@ -51,8 +45,3 @@ inline int Utils::count_ones_64(uint64_t word) {
5145

5246
return sum;
5347
}
54-
55-
inline void Utils::_atomic_xor_fetch_8(uint8_t &x1, uint8_t x2) {
56-
_OPENMP_GPU_PRAGMA("omp atomic", "omp critical")
57-
x1 ^= x2;
58-
}

0 commit comments

Comments
 (0)