1use singe_cuda::{data_type::DataTypeLike, types::DevicePtr};
2
3use singe_cusparse_sys as sys;
4
5use crate::{
6 context::Context,
7 error::Result,
8 matrix::SparseMatrixDescriptor,
9 operation::SpGemmDescriptor,
10 scalar::Scalar,
11 try_ffi,
12 types::{Operation, SpGemmAlgorithm},
13 utility::to_usize,
14};
15
16pub fn spgemm_work_estimation<Compute: DataTypeLike>(
17 ctx: &Context,
18 op_a: Operation,
19 op_b: Operation,
20 alpha: Scalar<'_, Compute>,
21 matrix_a: &SparseMatrixDescriptor,
22 matrix_b: &SparseMatrixDescriptor,
23 beta: Scalar<'_, Compute>,
24 matrix_c: &mut SparseMatrixDescriptor,
25 algorithm: SpGemmAlgorithm,
26 descriptor: &SpGemmDescriptor,
27 external_buffer: Option<DevicePtr>,
28) -> Result<usize> {
29 descriptor.ensure_context(ctx)?;
30 matrix_a.ensure_context(ctx)?;
31 matrix_b.ensure_context(ctx)?;
32 matrix_c.ensure_context(ctx)?;
33 ctx.bind()?;
34 ctx.require_scalar_pointer_mode(alpha, beta)?;
35
36 let mut size = 0;
37 unsafe {
38 try_ffi!(sys::cusparseSpGEMM_workEstimation(
39 ctx.as_raw(),
40 op_a.into(),
41 op_b.into(),
42 alpha.ptr().cast(),
43 matrix_a.as_raw_const(),
44 matrix_b.as_raw_const(),
45 beta.ptr().cast(),
46 matrix_c.as_raw(),
47 Compute::data_type().into(),
48 algorithm.into(),
49 descriptor.as_raw(),
50 &raw mut size,
51 external_buffer.unwrap_or(DevicePtr::null()).as_ptr() as _,
52 ))?;
53 }
54 to_usize(size, "spgemm work estimation buffer size")
55}
56
57pub fn spgemm_estimate_memory<Compute: DataTypeLike>(
58 ctx: &Context,
59 op_a: Operation,
60 op_b: Operation,
61 alpha: Scalar<'_, Compute>,
62 matrix_a: &SparseMatrixDescriptor,
63 matrix_b: &SparseMatrixDescriptor,
64 beta: Scalar<'_, Compute>,
65 matrix_c: &mut SparseMatrixDescriptor,
66 algorithm: SpGemmAlgorithm,
67 descriptor: &SpGemmDescriptor,
68 chunk_fraction: f32,
69 external_buffer: Option<DevicePtr>,
70) -> Result<(usize, usize)> {
71 descriptor.ensure_context(ctx)?;
72 matrix_a.ensure_context(ctx)?;
73 matrix_b.ensure_context(ctx)?;
74 matrix_c.ensure_context(ctx)?;
75 ctx.bind()?;
76 ctx.require_scalar_pointer_mode(alpha, beta)?;
77
78 let mut buffer_size3 = 0;
79 let mut buffer_size2 = 0;
80 unsafe {
81 try_ffi!(sys::cusparseSpGEMM_estimateMemory(
82 ctx.as_raw(),
83 op_a.into(),
84 op_b.into(),
85 alpha.ptr().cast(),
86 matrix_a.as_raw_const(),
87 matrix_b.as_raw_const(),
88 beta.ptr().cast(),
89 matrix_c.as_raw(),
90 Compute::data_type().into(),
91 algorithm.into(),
92 descriptor.as_raw(),
93 chunk_fraction,
94 &raw mut buffer_size3,
95 external_buffer.unwrap_or(DevicePtr::null()).as_ptr() as _,
96 &raw mut buffer_size2,
97 ))?;
98 }
99 Ok((
100 to_usize(buffer_size2, "spgemm compute buffer size")?,
101 to_usize(buffer_size3, "spgemm estimate buffer size")?,
102 ))
103}
104
105pub fn spgemm_compute<Compute: DataTypeLike>(
106 ctx: &Context,
107 op_a: Operation,
108 op_b: Operation,
109 alpha: Scalar<'_, Compute>,
110 matrix_a: &SparseMatrixDescriptor,
111 matrix_b: &SparseMatrixDescriptor,
112 beta: Scalar<'_, Compute>,
113 matrix_c: &mut SparseMatrixDescriptor,
114 algorithm: SpGemmAlgorithm,
115 descriptor: &SpGemmDescriptor,
116 external_buffer: Option<DevicePtr>,
117) -> Result<usize> {
118 descriptor.ensure_context(ctx)?;
119 matrix_a.ensure_context(ctx)?;
120 matrix_b.ensure_context(ctx)?;
121 matrix_c.ensure_context(ctx)?;
122 ctx.bind()?;
123 ctx.require_scalar_pointer_mode(alpha, beta)?;
124
125 let mut buffer_size2 = 0;
126 unsafe {
127 try_ffi!(sys::cusparseSpGEMM_compute(
128 ctx.as_raw(),
129 op_a.into(),
130 op_b.into(),
131 alpha.ptr().cast(),
132 matrix_a.as_raw_const(),
133 matrix_b.as_raw_const(),
134 beta.ptr().cast(),
135 matrix_c.as_raw(),
136 Compute::data_type().into(),
137 algorithm.into(),
138 descriptor.as_raw(),
139 &raw mut buffer_size2,
140 external_buffer.unwrap_or(DevicePtr::null()).as_ptr() as _,
141 ))?;
142 }
143 to_usize(buffer_size2, "spgemm compute buffer size")
144}
145
146pub fn spgemm_copy<Compute: DataTypeLike>(
147 ctx: &Context,
148 op_a: Operation,
149 op_b: Operation,
150 alpha: Scalar<'_, Compute>,
151 matrix_a: &SparseMatrixDescriptor,
152 matrix_b: &SparseMatrixDescriptor,
153 beta: Scalar<'_, Compute>,
154 matrix_c: &mut SparseMatrixDescriptor,
155 algorithm: SpGemmAlgorithm,
156 descriptor: &SpGemmDescriptor,
157) -> Result<()> {
158 descriptor.ensure_context(ctx)?;
159 matrix_a.ensure_context(ctx)?;
160 matrix_b.ensure_context(ctx)?;
161 matrix_c.ensure_context(ctx)?;
162 ctx.bind()?;
163 ctx.require_scalar_pointer_mode(alpha, beta)?;
164
165 unsafe {
166 try_ffi!(sys::cusparseSpGEMM_copy(
167 ctx.as_raw(),
168 op_a.into(),
169 op_b.into(),
170 alpha.ptr().cast(),
171 matrix_a.as_raw_const(),
172 matrix_b.as_raw_const(),
173 beta.ptr().cast(),
174 matrix_c.as_raw(),
175 Compute::data_type().into(),
176 algorithm.into(),
177 descriptor.as_raw(),
178 ))?;
179 }
180 Ok(())
181}
182
183pub fn spgemmreuse_work_estimation(
184 ctx: &Context,
185 op_a: Operation,
186 op_b: Operation,
187 matrix_a: &SparseMatrixDescriptor,
188 matrix_b: &SparseMatrixDescriptor,
189 matrix_c: &mut SparseMatrixDescriptor,
190 algorithm: SpGemmAlgorithm,
191 descriptor: &SpGemmDescriptor,
192 external_buffer1: Option<DevicePtr>,
193) -> Result<usize> {
194 descriptor.ensure_context(ctx)?;
195 matrix_a.ensure_context(ctx)?;
196 matrix_b.ensure_context(ctx)?;
197 matrix_c.ensure_context(ctx)?;
198 ctx.bind()?;
199 let mut size = 0;
200 unsafe {
201 try_ffi!(sys::cusparseSpGEMMreuse_workEstimation(
202 ctx.as_raw(),
203 op_a.into(),
204 op_b.into(),
205 matrix_a.as_raw_const(),
206 matrix_b.as_raw_const(),
207 matrix_c.as_raw(),
208 algorithm.into(),
209 descriptor.as_raw(),
210 &raw mut size,
211 external_buffer1.unwrap_or(DevicePtr::null()).as_ptr() as _,
212 ))?;
213 }
214 to_usize(size, "spgemmreuse work estimation buffer size")
215}
216
217pub fn spgemmreuse_nnz(
223 ctx: &Context,
224 op_a: Operation,
225 op_b: Operation,
226 matrix_a: &SparseMatrixDescriptor,
227 matrix_b: &SparseMatrixDescriptor,
228 matrix_c: &mut SparseMatrixDescriptor,
229 algorithm: SpGemmAlgorithm,
230 descriptor: &SpGemmDescriptor,
231 external_buffer2: Option<DevicePtr>,
232 external_buffer3: Option<DevicePtr>,
233 external_buffer4: Option<DevicePtr>,
234) -> Result<(usize, usize, usize)> {
235 descriptor.ensure_context(ctx)?;
236 matrix_a.ensure_context(ctx)?;
237 matrix_b.ensure_context(ctx)?;
238 matrix_c.ensure_context(ctx)?;
239 ctx.bind()?;
240 let mut size2 = 0;
241 let mut size3 = 0;
242 let mut size4 = 0;
243 unsafe {
244 try_ffi!(sys::cusparseSpGEMMreuse_nnz(
245 ctx.as_raw(),
246 op_a.into(),
247 op_b.into(),
248 matrix_a.as_raw_const(),
249 matrix_b.as_raw_const(),
250 matrix_c.as_raw(),
251 algorithm.into(),
252 descriptor.as_raw(),
253 &raw mut size2,
254 external_buffer2.unwrap_or(DevicePtr::null()).as_ptr() as _,
255 &raw mut size3,
256 external_buffer3.unwrap_or(DevicePtr::null()).as_ptr() as _,
257 &raw mut size4,
258 external_buffer4.unwrap_or(DevicePtr::null()).as_ptr() as _,
259 ))?;
260 }
261 Ok((
262 to_usize(size2, "spgemmreuse nnz buffer2 size")?,
263 to_usize(size3, "spgemmreuse nnz buffer3 size")?,
264 to_usize(size4, "spgemmreuse nnz buffer4 size")?,
265 ))
266}
267
268pub fn spgemmreuse_copy(
269 ctx: &Context,
270 op_a: Operation,
271 op_b: Operation,
272 matrix_a: &SparseMatrixDescriptor,
273 matrix_b: &SparseMatrixDescriptor,
274 matrix_c: &mut SparseMatrixDescriptor,
275 algorithm: SpGemmAlgorithm,
276 descriptor: &SpGemmDescriptor,
277 external_buffer5: Option<DevicePtr>,
278) -> Result<usize> {
279 descriptor.ensure_context(ctx)?;
280 matrix_a.ensure_context(ctx)?;
281 matrix_b.ensure_context(ctx)?;
282 matrix_c.ensure_context(ctx)?;
283 ctx.bind()?;
284 let mut size = 0;
285 unsafe {
286 try_ffi!(sys::cusparseSpGEMMreuse_copy(
287 ctx.as_raw(),
288 op_a.into(),
289 op_b.into(),
290 matrix_a.as_raw_const(),
291 matrix_b.as_raw_const(),
292 matrix_c.as_raw(),
293 algorithm.into(),
294 descriptor.as_raw(),
295 &raw mut size,
296 external_buffer5.unwrap_or(DevicePtr::null()).as_ptr() as _,
297 ))?;
298 }
299 to_usize(size, "spgemmreuse copy buffer size")
300}
301
302pub fn spgemmreuse_compute<Compute: DataTypeLike>(
303 ctx: &Context,
304 op_a: Operation,
305 op_b: Operation,
306 alpha: Scalar<'_, Compute>,
307 matrix_a: &SparseMatrixDescriptor,
308 matrix_b: &SparseMatrixDescriptor,
309 beta: Scalar<'_, Compute>,
310 matrix_c: &mut SparseMatrixDescriptor,
311 algorithm: SpGemmAlgorithm,
312 descriptor: &SpGemmDescriptor,
313) -> Result<()> {
314 descriptor.ensure_context(ctx)?;
315 matrix_a.ensure_context(ctx)?;
316 matrix_b.ensure_context(ctx)?;
317 matrix_c.ensure_context(ctx)?;
318 ctx.bind()?;
319 ctx.require_scalar_pointer_mode(alpha, beta)?;
320 unsafe {
321 try_ffi!(sys::cusparseSpGEMMreuse_compute(
322 ctx.as_raw(),
323 op_a.into(),
324 op_b.into(),
325 alpha.ptr().cast(),
326 matrix_a.as_raw_const(),
327 matrix_b.as_raw_const(),
328 beta.ptr().cast(),
329 matrix_c.as_raw(),
330 Compute::data_type().into(),
331 algorithm.into(),
332 descriptor.as_raw(),
333 ))?;
334 }
335 Ok(())
336}