Skip to content

Commit 96485f1

Browse files
authored
Add AOCL-Sparse to CI (#49)
* Add AOCL-Sparse to CI, update CMakeLists.txt. * Update AOCL-Sparse backend to support mixed CSR and CSC.
1 parent 08649fe commit 96485f1

File tree

10 files changed

+195
-88
lines changed

10 files changed

+195
-88
lines changed

.github/workflows/ci.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,27 @@ jobs:
9494
run: |
9595
./build/test/gtest/spblas-tests
9696
97+
aocl:
98+
runs-on: 'cpu_amd'
99+
steps:
100+
- uses: actions/checkout@v4
101+
- name: Add AOCL-Sparse to Environment
102+
run: |
103+
source /apps/spacks/current/share/spack/setup-env.sh
104+
echo "AOCLSPARSE_DIR=$(spack location -i aocl-sparse)" >> $GITHUB_ENV
105+
echo "AOCLUTILS_DIR=$(spack location -i aocl-utils)" >> $GITHUB_ENV
106+
- name: CMake
107+
run: |
108+
source /apps/spacks/current/share/spack/setup-env.sh
109+
spack load /ia2365b
110+
cmake -B build -DENABLE_AOCLSPARSE=ON
111+
- name: Build
112+
run: |
113+
make -C build -j `nproc`
114+
- name: Test
115+
run: |
116+
./build/test/gtest/spblas-tests
117+
97118
rocsparse:
98119
runs-on: 'gpu_amd'
99120
steps:

CMakeLists.txt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,24 @@ if (ENABLE_AOCLSPARSE)
4242
message(FATAL_ERROR "Environment variable AOCLUTILS_DIR must be set when the AOCLSPARSE is enabled.")
4343
endif()
4444
target_include_directories(spblas INTERFACE $ENV{AOCLSPARSE_DIR}/include $ENV{AOCLUTILS_DIR}/include)
45-
target_link_libraries(spblas INTERFACE $ENV{AOCLSPARSE_DIR}/lib/libaoclsparse.a $ENV{AOCLUTILS_DIR}/lib/libaoclutils.a)
45+
46+
find_library(AOCLSPARSE_LIBRARY NAMES aoclsparse libaoclsparse
47+
PATHS $ENV{AOCLSPARSE_DIR}/lib
48+
NO_DEFAULT_PATH)
49+
50+
find_library(AOCLUTILS_LIBRARY NAMES aoclutils libaoclutils
51+
PATHS $ENV{AOCLUTILS_DIR}/lib
52+
NO_DEFAULT_PATH)
53+
54+
if (NOT AOCLSPARSE_LIBRARY)
55+
message(FATAL_ERROR "Could not find AOCL-Sparse library in $ENV{AOCLSPARSE_DIR}/lib")
56+
endif()
57+
if (NOT AOCLUTILS_LIBRARY)
58+
message(FATAL_ERROR "Could not find AOCL-Utils library in $ENV{AOCLUTILS_DIR}/lib")
59+
endif()
60+
61+
target_link_libraries(spblas INTERFACE ${AOCLSPARSE_LIBRARY} ${AOCLUTILS_LIBRARY})
62+
4663
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSPBLAS_ENABLE_AOCLSPARSE")
4764
endif()
4865

include/spblas/vendor/aoclsparse/aocl_wrappers.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,32 @@ inline aoclsparse_status aoclsparse_create_csr<double>(
119119
return aoclsparse_create_dcsr(mat, base, M, N, nnz, row_ptr, col_idx, val);
120120
}
121121

122+
template <class T>
123+
inline aoclsparse_status
124+
aoclsparse_create_csc(aoclsparse_matrix* mat, aoclsparse_index_base base,
125+
aoclsparse_int M, aoclsparse_int N, aoclsparse_int nnz,
126+
aoclsparse_int* col_ptr, aoclsparse_int* row_idx,
127+
T* val) {
128+
log_warning("matrix creating with this data type is currently not supported");
129+
return aoclsparse_status_not_implemented;
130+
}
131+
132+
template <>
133+
inline aoclsparse_status
134+
aoclsparse_create_csc<float>(aoclsparse_matrix* mat, aoclsparse_index_base base,
135+
aoclsparse_int M, aoclsparse_int N,
136+
aoclsparse_int nnz, aoclsparse_int* col_ptr,
137+
aoclsparse_int* row_idx, float* val) {
138+
return aoclsparse_create_scsc(mat, base, M, N, nnz, col_ptr, row_idx, val);
139+
}
140+
template <>
141+
inline aoclsparse_status aoclsparse_create_csc<double>(
142+
aoclsparse_matrix* mat, aoclsparse_index_base base, aoclsparse_int M,
143+
aoclsparse_int N, aoclsparse_int nnz, aoclsparse_int* col_ptr,
144+
aoclsparse_int* row_idx, double* val) {
145+
return aoclsparse_create_dcsc(mat, base, M, N, nnz, col_ptr, row_idx, val);
146+
}
147+
122148
template <typename T>
123149
inline aoclsparse_status
124150
aoclsparse_export_csr(const aoclsparse_matrix mat, aoclsparse_index_base* base,
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#pragma once
2+
3+
#include <spblas/vendor/aoclsparse/aocl_wrappers.hpp>
4+
5+
#include <spblas/detail/view_inspectors.hpp>
6+
7+
namespace spblas {
8+
9+
namespace __aoclsparse {
10+
11+
template <matrix M>
12+
requires __detail::is_csr_view_v<M>
13+
aoclsparse_matrix create_matrix_handle(M&& m) {
14+
aoclsparse_matrix handle = nullptr;
15+
aoclsparse_status status = __aoclsparse::aoclsparse_create_csr(
16+
&handle, aoclsparse_index_base_zero, m.shape()[0], m.shape()[1], m.size(),
17+
m.rowptr().data(), m.colind().data(), m.values().data());
18+
19+
if (status != aoclsparse_status_success) {
20+
throw std::runtime_error("create_matrix_handle: AOCL-Sparse failed while "
21+
"creating matrix handle.");
22+
}
23+
24+
return handle;
25+
}
26+
27+
template <matrix M>
28+
requires __detail::is_csc_view_v<M>
29+
aoclsparse_matrix create_matrix_handle(M&& m) {
30+
aoclsparse_matrix handle = nullptr;
31+
aoclsparse_status status = __aoclsparse::aoclsparse_create_csr(
32+
&handle, aoclsparse_index_base_zero, m.shape()[1], m.shape()[0], m.size(),
33+
m.colptr().data(), m.rowind().data(), m.values().data());
34+
35+
if (status != aoclsparse_status_success) {
36+
throw std::runtime_error("create_matrix_handle: AOCL-Sparse failed while "
37+
"creating matrix handle.");
38+
}
39+
40+
return handle;
41+
}
42+
43+
template <matrix M>
44+
aoclsparse_operation get_transpose(M&& m) {
45+
static_assert(__detail::has_csr_base<M> || __detail::has_csc_base<M>);
46+
if constexpr (__detail::has_base<M>) {
47+
return get_transpose(m.base());
48+
} else if constexpr (__detail::is_csr_view_v<M>) {
49+
return aoclsparse_operation_none;
50+
} else if constexpr (__detail::is_csc_view_v<M>) {
51+
return aoclsparse_operation_transpose;
52+
}
53+
}
54+
55+
} // namespace __aoclsparse
56+
57+
} // namespace spblas
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
#include "create_matrix_handle.hpp"

include/spblas/vendor/aoclsparse/spgemm_impl.hpp

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99

1010
#pragma once
1111

12-
#include "aoclsparse.h"
12+
#include <aoclsparse.h>
1313
#include <cstdint>
1414

1515
#include "aocl_wrappers.hpp"
16+
#include "detail/detail.hpp"
1617
#include <fmt/core.h>
18+
#include <spblas/algorithms/transposed.hpp>
1719
#include <spblas/detail/log.hpp>
1820
#include <spblas/detail/operation_info_t.hpp>
1921
#include <spblas/detail/ranges.hpp>
@@ -30,8 +32,9 @@
3032
namespace spblas {
3133

3234
template <matrix A, matrix B, matrix C>
33-
requires(__detail::has_csr_base<A>) &&
34-
(__detail::has_csr_base<B>) && __detail::is_csr_view_v<C>
35+
requires(__detail::has_csr_base<A> || __detail::has_csc_base<A>) &&
36+
(__detail::has_csr_base<B> || __detail::has_csc_base<B>) &&
37+
__detail::is_csr_view_v<C>
3538
operation_info_t multiply_compute(A&& a, B&& b, C&& c) {
3639
log_trace("");
3740
auto a_base = __detail::get_ultimate_base(a);
@@ -41,32 +44,27 @@ operation_info_t multiply_compute(A&& a, B&& b, C&& c) {
4144
using I = tensor_index_t<C>;
4245
using O = tensor_offset_t<C>;
4346

44-
aoclsparse_matrix csrA = nullptr;
45-
aoclsparse_mat_descr descrA;
47+
aoclsparse_matrix csrA = __aoclsparse::create_matrix_handle(a_base);
48+
aoclsparse_matrix csrB = __aoclsparse::create_matrix_handle(b_base);
49+
50+
aoclsparse_operation opA = __aoclsparse::get_transpose(a);
51+
aoclsparse_operation opB = __aoclsparse::get_transpose(b);
52+
53+
aoclsparse_mat_descr descrA = NULL;
4654
aoclsparse_status status = aoclsparse_create_mat_descr(&descrA);
4755
if (status != aoclsparse_status_success) {
4856
fmt::print("\t descr creation failed\n");
4957
}
5058
aoclsparse_set_mat_type(descrA, aoclsparse_matrix_type_general);
51-
aoclsparse_index_base indexingA = aoclsparse_index_base_zero;
52-
aoclsparse_operation opA = aoclsparse_operation_none;
5359

54-
const index_t a_nrows = __backend::shape(a_base)[0];
55-
const index_t a_ncols = __backend::shape(a_base)[1];
56-
57-
aoclsparse_matrix csrB = nullptr;
58-
aoclsparse_mat_descr descrB;
60+
aoclsparse_mat_descr descrB = NULL;
5961
status = aoclsparse_create_mat_descr(&descrB);
6062
if (status != aoclsparse_status_success) {
6163
fmt::print("\t descr creation failed\n");
6264
}
6365

6466
aoclsparse_set_mat_type(descrB, aoclsparse_matrix_type_general);
6567
aoclsparse_index_base indexingB = aoclsparse_index_base_zero;
66-
aoclsparse_operation opB = aoclsparse_operation_none;
67-
68-
const index_t b_nrows = __backend::shape(b_base)[0];
69-
const index_t b_ncols = __backend::shape(b_base)[1];
7068

7169
aoclsparse_matrix csrC = nullptr;
7270
aoclsparse_index_base indexingC = aoclsparse_index_base_zero;
@@ -76,22 +74,6 @@ operation_info_t multiply_compute(A&& a, B&& b, C&& c) {
7674
index_t* c_colind = nullptr;
7775
T* c_values = nullptr;
7876

79-
const aoclsparse_int nnzA = a_base.rowptr().data()[a_nrows] - indexingA;
80-
const aoclsparse_int nnzB = b_base.rowptr().data()[b_nrows] - indexingB;
81-
82-
status = __aoclsparse::aoclsparse_create_csr(
83-
&csrA, indexingA, a_nrows, a_ncols, nnzA, a_base.rowptr().data(),
84-
a_base.colind().data(), a_base.values().data());
85-
if (status != aoclsparse_status_success) {
86-
fmt::print("\t csr matrix A creation failed\n");
87-
}
88-
status = __aoclsparse::aoclsparse_create_csr(
89-
&csrB, indexingB, b_nrows, b_ncols, nnzB, b_base.rowptr().data(),
90-
b_base.colind().data(), b_base.values().data());
91-
if (status != aoclsparse_status_success) {
92-
fmt::print("\t csr matrix B creation failed\n");
93-
}
94-
9577
aoclsparse_request request = aoclsparse_stage_nnz_count;
9678
status =
9779
aoclsparse_sp2m(opA, descrA, csrA, opB, descrB, csrB, request, &csrC);
@@ -108,20 +90,22 @@ operation_info_t multiply_compute(A&& a, B&& b, C&& c) {
10890
// Check: csrA and csrB destroyed when the operation_info destructor is
10991
// called?
11092

93+
aoclsparse_destroy_mat_descr(descrA);
94+
aoclsparse_destroy_mat_descr(descrB);
11195
return operation_info_t{
11296
index<>{__backend::shape(c)[0], __backend::shape(c)[1]}, c_nnz,
11397
__aoclsparse::operation_state_t{csrA, csrB, csrC}};
11498
}
11599

116100
template <matrix A, matrix B, matrix C>
117-
requires(__detail::has_csr_base<A>) &&
118-
(__detail::has_csr_base<B>) && __detail::is_csr_view_v<C>
101+
requires(__detail::has_csr_base<A> || __detail::has_csc_base<A>) &&
102+
(__detail::has_csr_base<B> || __detail::has_csc_base<B>) &&
103+
__detail::is_csr_view_v<C>
119104
void multiply_fill(operation_info_t& info, A&& a, B&& b, C&& c) {
120105
log_trace("");
121106

122107
auto a_base = __detail::get_ultimate_base(a);
123108
auto b_base = __detail::get_ultimate_base(b);
124-
auto c_base = __detail::get_ultimate_base(c);
125109

126110
using T = tensor_scalar_t<C>;
127111
using I = tensor_index_t<C>;
@@ -135,35 +119,30 @@ void multiply_fill(operation_info_t& info, A&& a, B&& b, C&& c) {
135119
aoclsparse_matrix csrC = info.state_.c_handle;
136120
offset_t c_nnz = info.result_nnz();
137121

138-
aoclsparse_mat_descr descrA;
122+
aoclsparse_operation opA = __aoclsparse::get_transpose(a);
123+
aoclsparse_operation opB = __aoclsparse::get_transpose(b);
124+
125+
aoclsparse_mat_descr descrA = NULL;
139126
aoclsparse_status status = aoclsparse_create_mat_descr(&descrA);
140127
if (status != aoclsparse_status_success) {
141128
fmt::print("\t descr creation failed\n");
142129
}
143130

144131
aoclsparse_set_mat_type(descrA, aoclsparse_matrix_type_general);
145132
aoclsparse_index_base indexingA = aoclsparse_index_base_zero;
146-
aoclsparse_operation opA = aoclsparse_operation_none;
147-
148-
const index_t a_nrows = __backend::shape(a_base)[0];
149-
const index_t a_ncols = __backend::shape(a_base)[1];
150133

151-
aoclsparse_mat_descr descrB;
134+
aoclsparse_mat_descr descrB = NULL;
152135
status = aoclsparse_create_mat_descr(&descrB);
153136
if (status != aoclsparse_status_success) {
154137
fmt::print("\t descr creation failed\n");
155138
}
156139

157140
aoclsparse_set_mat_type(descrB, aoclsparse_matrix_type_general);
158141
aoclsparse_index_base indexingB = aoclsparse_index_base_zero;
159-
aoclsparse_operation opB = aoclsparse_operation_none;
160-
161-
const index_t b_nrows = __backend::shape(b_base)[0];
162-
const index_t b_ncols = __backend::shape(b_base)[1];
163142

164143
aoclsparse_index_base indexingC = aoclsparse_index_base_zero;
165-
index_t c_nrows = __backend::shape(c_base)[0];
166-
index_t c_ncols = __backend::shape(c_base)[1];
144+
index_t c_nrows = __backend::shape(c)[0];
145+
index_t c_ncols = __backend::shape(c)[1];
167146
offset_t* c_rowptr = nullptr;
168147
index_t* c_colind = nullptr;
169148
T* c_values = nullptr;
@@ -194,6 +173,24 @@ void multiply_fill(operation_info_t& info, A&& a, B&& b, C&& c) {
194173
if (alpha_optional.has_value()) {
195174
scale(alpha, c);
196175
}
176+
aoclsparse_destroy_mat_descr(descrA);
177+
aoclsparse_destroy_mat_descr(descrB);
178+
}
179+
180+
template <matrix A, matrix B, matrix C>
181+
requires(__detail::has_csr_base<A> || __detail::has_csc_base<A>) &&
182+
(__detail::has_csr_base<B> || __detail::has_csc_base<B>) &&
183+
__detail::is_csc_view_v<C>
184+
operation_info_t multiply_compute(A&& a, B&& b, C&& c) {
185+
return multiply_compute(transposed(b), transposed(a), transposed(c));
186+
}
187+
188+
template <matrix A, matrix B, matrix C>
189+
requires((__detail::has_csr_base<A> || __detail::has_csc_base<A>) &&
190+
(__detail::has_csr_base<B> || __detail::has_csc_base<B>) &&
191+
__detail::is_csc_view_v<C>)
192+
void multiply_fill(operation_info_t& info, A&& a, B&& b, C&& c) {
193+
multiply_fill(info, transposed(b), transposed(a), transposed(c));
197194
}
198195

199196
} // namespace spblas

0 commit comments

Comments
 (0)