Skip to content

Commit 3f09614

Browse files
committed
[Code] Add utility for csr build/extract logic
1 parent 75a1236 commit 3f09614

File tree

10 files changed

+163
-149
lines changed

10 files changed

+163
-149
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ prototyping algorithms on a local computer for later running on a powerful serve
5959

6060
## Installation
6161

62-
If you running OS **Ubuntu 20.04** or higher you can download the official
63-
PyPI **pycubool** python package, which includes compiled library source
62+
If you are running OS **Ubuntu 20.04** or higher you can download the official
63+
PyPI **pycubool** python package, which includes compiled library source code
6464
with Cuda and Sequential computations support. Installation process
6565
requires only `python3` to be installed on your machine. Python can be installed
6666
as follows [link](https://phoenixnap.com/kb/how-to-install-python-3-ubuntu).
6767

68-
If all requirements satisfied, run the following command to install PyPI package:
68+
If all requirements are satisfied, run the following command to install PyPI package:
6969
```shell script
7070
$ python3 -m pip install -i https://test.pypi.org/simple/ pycubool
7171
```
@@ -274,7 +274,7 @@ cuBool
274274
│ │ └── sequential - fallback cpu backend
275275
│ ├── utils - testing utilities
276276
│ └── tests - gtest-based unit-tests collection
277-
├── python - pycubool related source
277+
├── python - pycubool related sources
278278
│ ├── pycubool - cubool library wrapper for python (similar to pygraphblas)
279279
│ ├── tests - regression tests for python wrapper
280280
│ └── data - generate data for pycubool regression tests

cubool/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ set(CUBOOL_SOURCES
2626
sources/io/logger.hpp
2727
sources/utils/exclusive_scan.hpp
2828
sources/utils/timer.hpp
29+
sources/utils/csr_utils.cpp
30+
sources/utils/csr_utils.hpp
2931
)
3032

3133
set(CUBOOL_C_API_SOURCES
@@ -72,8 +74,8 @@ if (CUBOOL_WITH_CUDA)
7274
sources/cuda/instance.cpp
7375
sources/cuda/matrix_csr.hpp
7476
sources/cuda/matrix_csr.cu
75-
sources/cuda/matrix_csr_build.cpp
76-
sources/cuda/matrix_csr_extract.cpp
77+
sources/cuda/matrix_csr_build.cu
78+
sources/cuda/matrix_csr_extract.cu
7779
sources/cuda/matrix_csr_ewiseadd.cu
7880
sources/cuda/matrix_csr_kronecker.cu
7981
sources/cuda/matrix_csr_multiply.cu

cubool/sources/cuda/matrix_csr.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ namespace cubool {
4646
void setElement(index i, index j) override;
4747
void build(const index *rows, const index *cols, size_t nvals, bool isSorted, bool noDuplicates) override;
4848
void extract(index* rows, index* cols, size_t &nvals) override;
49-
void extractSubMatrix(const MatrixBase &otherBase, index i, index j, index nrows, index ncols,
50-
bool checkTime) override;
49+
void extractSubMatrix(const MatrixBase &otherBase, index i, index j, index nrows, index ncols, bool checkTime) override;
5150

5251
void clone(const MatrixBase &other) override;
5352
void transpose(const MatrixBase &other, bool checkTime) override;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**********************************************************************************/
2+
/* MIT License */
3+
/* */
4+
/* Copyright (c) 2020, 2021 JetBrains-Research */
5+
/* */
6+
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
7+
/* of this software and associated documentation files (the "Software"), to deal */
8+
/* in the Software without restriction, including without limitation the rights */
9+
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
10+
/* copies of the Software, and to permit persons to whom the Software is */
11+
/* furnished to do so, subject to the following conditions: */
12+
/* */
13+
/* The above copyright notice and this permission notice shall be included in all */
14+
/* copies or substantial portions of the Software. */
15+
/* */
16+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
17+
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
18+
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
19+
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
20+
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
21+
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
22+
/* SOFTWARE. */
23+
/**********************************************************************************/
24+
25+
#include <cuda/matrix_csr.hpp>
26+
#include <utils/csr_utils.hpp>
27+
28+
namespace cubool {
29+
30+
void MatrixCsr::build(const index *rows, const index *cols, size_t nvals, bool isSorted, bool noDuplicates) {
31+
if (nvals == 0) {
32+
mMatrixImpl.zero_dim(); // no content, empty matrix
33+
return;
34+
}
35+
36+
// Build csr structure and store on cpu side
37+
std::vector<index> rowOffsets;
38+
std::vector<index> colIndices;
39+
40+
CsrUtils::buildFromData(getNrows(), getNcols(), rows, cols, nvals, rowOffsets, colIndices, isSorted, noDuplicates);
41+
42+
// Move actual data to the matrix implementation
43+
this->transferToDevice(rowOffsets, colIndices);
44+
}
45+
46+
}

cubool/sources/cuda/matrix_csr_extract.cpp renamed to cubool/sources/cuda/matrix_csr_extract.cu

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
/**********************************************************************************/
2424

2525
#include <cuda/matrix_csr.hpp>
26-
#include <vector>
26+
#include <utils/csr_utils.hpp>
2727

2828
namespace cubool {
2929

@@ -40,16 +40,7 @@ namespace cubool {
4040

4141
this->transferFromDevice(rowOffsets, colIndices);
4242

43-
// Iterate over csr formatted data
44-
size_t idx = 0;
45-
for (index i = 0; i < getNrows(); i++) {
46-
for (index j = rowOffsets[i]; j < rowOffsets[i + 1]; j++) {
47-
rows[idx] = i;
48-
cols[idx] = colIndices[j];
49-
50-
idx += 1;
51-
}
52-
}
43+
CsrUtils::extractData(getNrows(), getNcols(), rows, cols, nvals, rowOffsets, colIndices);
5344
}
5445
}
5546

cubool/sources/sequential/sq_matrix.cpp

Lines changed: 4 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
#include <sequential/sq_ewiseadd.hpp>
3030
#include <sequential/sq_spgemm.hpp>
3131
#include <sequential/sq_reduce.hpp>
32-
#include <utils/exclusive_scan.hpp>
32+
#include <utils/csr_utils.hpp>
3333
#include <core/error.hpp>
34-
#include <algorithm>
3534
#include <cassert>
3635

3736
namespace cubool {
@@ -53,110 +52,20 @@ namespace cubool {
5352
auto ncols = mData.ncols;
5453

5554
mData.rowOffsets.clear();
56-
mData.rowOffsets.resize(nrows + 1, 0);
5755
mData.colIndices.clear();
58-
mData.colIndices.resize(nvals);
5956

60-
if (nvals == 0)
61-
return;
62-
63-
assert(rows);
64-
assert(cols);
65-
66-
for (size_t k = 0; k < nvals; k++) {
67-
auto i = rows[k];
68-
auto j = cols[k];
69-
70-
CHECK_RAISE_ERROR(i < nrows, InvalidArgument, "Index out of matrix bound");
71-
CHECK_RAISE_ERROR(j < ncols, InvalidArgument, "Index out of matrix bound");
72-
73-
mData.rowOffsets[i]++;
74-
}
75-
76-
exclusive_scan(mData.rowOffsets.begin(), mData.rowOffsets.end(), 0);
77-
78-
std::vector<size_t> writeOffset(nrows, 0);
79-
for (size_t k = 0; k < nvals; k++) {
80-
auto i = rows[k];
81-
auto j = cols[k];
82-
83-
mData.colIndices[mData.rowOffsets[i] + writeOffset[i]] = j;
84-
writeOffset[i] += 1;
85-
}
86-
87-
if (!isSorted) {
88-
for (size_t i = 0; i < getNrows(); i++) {
89-
auto begin = mData.rowOffsets[i];
90-
auto end = mData.rowOffsets[i + 1];
91-
92-
// Sort col values within row
93-
std::sort(mData.colIndices.begin() + begin, mData.colIndices.begin() + end, [](const index& a, const index& b) {
94-
return a < b;
95-
});
96-
}
97-
}
98-
99-
if (!noDuplicates) {
100-
size_t unique = 0;
101-
for (size_t i = 0; i < getNrows(); i++) {
102-
index prev = std::numeric_limits<index>::max();
103-
104-
for (size_t k = mData.rowOffsets[i]; k < mData.rowOffsets[i + 1]; k++) {
105-
if (prev != mData.colIndices[k]) {
106-
unique += 1;
107-
}
108-
109-
prev = mData.colIndices[k];
110-
}
111-
}
112-
113-
std::vector<index> rowOffsetsReduced;
114-
rowOffsetsReduced.resize(getNrows() + 1, 0);
115-
116-
std::vector<index> colIndicesReduced;
117-
colIndicesReduced.reserve(unique);
118-
119-
for (size_t i = 0; i < getNrows(); i++) {
120-
index prev = std::numeric_limits<index>::max();
121-
122-
for (size_t k = mData.rowOffsets[i]; k < mData.rowOffsets[i + 1]; k++) {
123-
if (prev != mData.colIndices[k]) {
124-
rowOffsetsReduced[i] += 1;
125-
colIndicesReduced.push_back(mData.colIndices[k]);
126-
}
127-
128-
prev = mData.colIndices[k];
129-
}
130-
}
131-
132-
// Exclusive scan to eval rows offsets
133-
exclusive_scan(rowOffsetsReduced.begin(), rowOffsetsReduced.end(), 0);
134-
135-
// Now result in respective place
136-
std::swap(mData.rowOffsets, rowOffsetsReduced);
137-
std::swap(mData.colIndices, colIndicesReduced);
138-
}
57+
// Call utility to build csr row offsets and column indices and store in mData vectors
58+
CsrUtils::buildFromData(nrows, ncols, rows, cols, nvals, mData.rowOffsets, mData.colIndices, isSorted, noDuplicates);
13959

14060
mData.nvals = mData.colIndices.size();
14161
}
14262

14363
void SqMatrix::extract(index *rows, index *cols, size_t &nvals) {
14464
assert(nvals >= getNvals());
145-
14665
nvals = getNvals();
14766

14867
if (nvals > 0) {
149-
assert(rows);
150-
assert(cols);
151-
152-
size_t id = 0;
153-
for (index i = 0; i < getNrows(); i++) {
154-
for (index k = mData.rowOffsets[i]; k < mData.rowOffsets[i + 1]; k++) {
155-
rows[id] = i;
156-
cols[id] = mData.colIndices[k];
157-
id += 1;
158-
}
159-
}
68+
CsrUtils::extractData(getNrows(), getNcols(), rows, cols, nvals, mData.rowOffsets, mData.colIndices);
16069
}
16170
}
16271

cubool/sources/cuda/matrix_csr_build.cpp renamed to cubool/sources/utils/csr_utils.cpp

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,53 @@
2222
/* SOFTWARE. */
2323
/**********************************************************************************/
2424

25-
#include <cuda/matrix_csr.hpp>
25+
#include <utils/csr_utils.hpp>
2626
#include <utils/exclusive_scan.hpp>
27-
#include <vector>
27+
#include <core/error.hpp>
2828
#include <algorithm>
29+
#include <cassert>
2930

3031
namespace cubool {
3132

32-
void MatrixCsr::build(const index *rows, const index *cols, size_t nvals, bool isSorted, bool noDuplicates) {
33-
if (nvals == 0) {
34-
mMatrixImpl.zero_dim(); // no content, empty matrix
35-
return;
36-
}
37-
38-
std::vector<index> rowOffsets;
39-
rowOffsets.resize(getNrows() + 1, 0);
33+
void CsrUtils::buildFromData(size_t nrows, size_t ncols,
34+
const index *rows, const index *cols, size_t nvals,
35+
std::vector<index> &rowOffsets, std::vector<index> &colIndices,
36+
bool isSorted, bool noDuplicates) {
4037

41-
std::vector<index> colIndices;
38+
rowOffsets.resize(nrows + 1, 0);
4239
colIndices.resize(nvals);
4340

44-
// Compute nnz per row
45-
for (size_t idx = 0; idx < nvals; idx++) {
46-
index i = rows[idx];
47-
index j = cols[idx];
41+
std::fill(rowOffsets.begin(), rowOffsets.end(), 0);
4842

49-
CHECK_RAISE_ERROR(i < getNrows() && j < getNcols(), InvalidArgument, "Out of matrix bounds value");
43+
if (nvals == 0)
44+
return;
5045

51-
rowOffsets[i] += 1;
52-
}
46+
assert(rows);
47+
assert(cols);
5348

54-
// Exclusive scan to eval rows offsets
55-
::cubool::exclusive_scan(rowOffsets.begin(), rowOffsets.end(), 0);
49+
for (size_t k = 0; k < nvals; k++) {
50+
auto i = rows[k];
51+
auto j = cols[k];
5652

57-
// Write offsets for cols
58-
std::vector<size_t> writeOffsets(getNrows(), 0);
53+
CHECK_RAISE_ERROR(i < nrows, InvalidArgument, "Index out of matrix bounds");
54+
CHECK_RAISE_ERROR(j < ncols, InvalidArgument, "Index out of matrix bounds");
5955

60-
for (size_t idx = 0; idx < nvals; idx++) {
61-
index i = rows[idx];
62-
index j = cols[idx];
56+
rowOffsets[i]++;
57+
}
6358

64-
colIndices[rowOffsets[i] + writeOffsets[i]] = j;
65-
writeOffsets[i] += 1;
59+
exclusive_scan(rowOffsets.begin(), rowOffsets.end(), 0);
60+
61+
std::vector<size_t> writeOffset(nrows, 0);
62+
for (size_t k = 0; k < nvals; k++) {
63+
auto i = rows[k];
64+
auto j = cols[k];
65+
66+
colIndices[rowOffsets[i] + writeOffset[i]] = j;
67+
writeOffset[i] += 1;
6668
}
6769

6870
if (!isSorted) {
69-
for (size_t i = 0; i < getNrows(); i++) {
71+
for (size_t i = 0; i < nrows; i++) {
7072
auto begin = rowOffsets[i];
7173
auto end = rowOffsets[i + 1];
7274

@@ -77,10 +79,9 @@ namespace cubool {
7779
}
7880
}
7981

80-
// Reduce duplicated values
8182
if (!noDuplicates) {
8283
size_t unique = 0;
83-
for (size_t i = 0; i < getNrows(); i++) {
84+
for (size_t i = 0; i < nrows; i++) {
8485
index prev = std::numeric_limits<index>::max();
8586

8687
for (size_t k = rowOffsets[i]; k < rowOffsets[i + 1]; k++) {
@@ -93,12 +94,12 @@ namespace cubool {
9394
}
9495

9596
std::vector<index> rowOffsetsReduced;
96-
rowOffsetsReduced.resize(getNrows() + 1, 0);
97+
rowOffsetsReduced.resize(nrows + 1, 0);
9798

9899
std::vector<index> colIndicesReduced;
99100
colIndicesReduced.reserve(unique);
100101

101-
for (size_t i = 0; i < getNrows(); i++) {
102+
for (size_t i = 0; i < nrows; i++) {
102103
index prev = std::numeric_limits<index>::max();
103104

104105
for (size_t k = rowOffsets[i]; k < rowOffsets[i + 1]; k++) {
@@ -112,15 +113,28 @@ namespace cubool {
112113
}
113114

114115
// Exclusive scan to eval rows offsets
115-
::cubool::exclusive_scan(rowOffsetsReduced.begin(), rowOffsetsReduced.end(), 0);
116+
exclusive_scan(rowOffsetsReduced.begin(), rowOffsetsReduced.end(), 0);
116117

117118
// Now result in respective place
118119
std::swap(rowOffsets, rowOffsetsReduced);
119120
std::swap(colIndices, colIndicesReduced);
120121
}
122+
}
121123

122-
// Move actual data to the matrix implementation
123-
this->transferToDevice(rowOffsets, colIndices);
124+
void CsrUtils::extractData(size_t nrows, size_t ncols,
125+
index *rows, index *cols, size_t nvals,
126+
const std::vector<index> &rowOffsets, const std::vector<index> &colIndices) {
127+
assert(rows);
128+
assert(cols);
129+
130+
size_t id = 0;
131+
for (index i = 0; i < nrows; i++) {
132+
for (index k = rowOffsets[i]; k < rowOffsets[i + 1]; k++) {
133+
rows[id] = i;
134+
cols[id] = colIndices[k];
135+
id += 1;
136+
}
137+
}
124138
}
125139

126140
}

0 commit comments

Comments
 (0)