singe-cutensor-sys 0.1.0-alpha.7

Low-level FFI bindings for the NVIDIA cuTENSOR tensor algebra library.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
/* automatically generated by rust-bindgen 0.72.1 */

#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub enum cutensorComputeType_t {
    CUTENSOR_COMPUTE_16F = 1,
    CUTENSOR_COMPUTE_16BF = 1024,
    CUTENSOR_COMPUTE_TF32 = 4096,
    CUTENSOR_COMPUTE_3XTF32 = 8192,
    CUTENSOR_COMPUTE_32F = 4,
    CUTENSOR_COMPUTE_64F = 16,
    CUTENSOR_COMPUTE_8U = 64,
    CUTENSOR_COMPUTE_8I = 256,
    CUTENSOR_COMPUTE_32U = 128,
    CUTENSOR_COMPUTE_32I = 512,
}
/// Enumerated device codes for host-side tensors.
#[repr(i32)]
#[derive(
    Debug,
    Copy,
    Clone,
    Hash,
    PartialOrd,
    Ord,
    PartialEq,
    Eq,
    TryFromPrimitive,
    IntoPrimitive,
)]
pub enum cutensorMgHostDevice_t {
    /// The memory is located on the host in regular memory.
    CUTENSOR_MG_DEVICE_HOST = -1,
    /// The memory is located on the host in pinned memory.
    CUTENSOR_MG_DEVICE_HOST_PINNED = -2,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorMgHandle_s {
    _unused: [u8; 0],
}
/// Encodes the devices that participate in operations.
///
/// The handle contains information about each device that participates in operations as well as host threads to orchestrate host-to-device operations.
pub type cutensorMgHandle_t = *mut cutensorMgHandle_s;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorMgTensorDescriptor_s {
    _unused: [u8; 0],
}
/// Represents a tensor that may be distributed.
///
/// The tensor is laid out in a block-cyclic fashion across devices. It may either be fully located on the host, or distributed across multiple devices.
pub type cutensorMgTensorDescriptor_t = *mut cutensorMgTensorDescriptor_s;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorMgCopyDescriptor_s {
    _unused: [u8; 0],
}
/// Describes the copy of a tensor from one data layout to another.
///
/// It may describe the full Cartesian product of copy from and to host, single device, and multiple devices, as well as permutations and layout changes.
pub type cutensorMgCopyDescriptor_t = *mut cutensorMgCopyDescriptor_s;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorMgCopyPlan_s {
    _unused: [u8; 0],
}
/// Describes a specific way to implement the copy operation.
///
/// It encodes blockings and other implementation details, and may be reused to reduce planning overhead.
pub type cutensorMgCopyPlan_t = *mut cutensorMgCopyPlan_s;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorMgContractionDescriptor_s {
    _unused: [u8; 0],
}
/// Describes the contraction of two tensors into a third tensor with an optional source.
///
/// Only supports device-side tensors.
pub type cutensorMgContractionDescriptor_t = *mut cutensorMgContractionDescriptor_s;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorMgContractionFind_s {
    _unused: [u8; 0],
}
/// Describes the algorithmic details of implementing a tensor contraction.
pub type cutensorMgContractionFind_t = *mut cutensorMgContractionFind_s;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct cutensorMgContractionPlan_s {
    _unused: [u8; 0],
}
/// Describes a specific way to implement a contraction operation.
///
/// It encodes blockings, permutations and other implementation details, and may be reused to reduce planning overhead.
pub type cutensorMgContractionPlan_t = *mut cutensorMgContractionPlan_s;
/// Represents the selected algorithm when planning for a contraction operation.
#[repr(i32)]
#[derive(
    Debug,
    Copy,
    Clone,
    Hash,
    PartialOrd,
    Ord,
    PartialEq,
    Eq,
    TryFromPrimitive,
    IntoPrimitive,
)]
pub enum cutensorMgAlgo_t {
    /// Lets the internal heuristic choose.
    CUTENSORMG_ALGO_DEFAULT = -1,
}
#[repr(u32)]
#[derive(
    Debug,
    Copy,
    Clone,
    Hash,
    PartialOrd,
    Ord,
    PartialEq,
    Eq,
    TryFromPrimitive,
    IntoPrimitive,
)]
pub enum cutensorMgContractionFindAttribute_t {
    CUTENSORMG_CONTRACTION_FIND_ATTRIBUTE_MAX = 65535,
}
unsafe extern "C" {
    /// Create a library handle.
    ///
    /// The handle contains information about the devices that should be participating in calculations. All devices that hold any tensor data or participate in any of cuTENSORMg’s operations should also be included in the handle. Each device may only occur once in the list. It is advisable that all devices are identical (i.e., have the same peak performance) to avoid load-balancing issues, and are connected via NVLink to avoid costly device-host-device transfers. This call will enable peering between all devices that have been passed to it, if possible.
    ///
    /// Remark
    ///
    /// blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The resulting library handle.
    /// - `numDevices`: The number of devices participating in all subsequent computations.
    /// - `devices`: The devices that participate in all computations.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCreate(
        handle: *mut cutensorMgHandle_t,
        numDevices: u32,
        devices: *const i32,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Destroy a library handle.
    ///
    /// All outstanding operations must be completed before calling this function. Frees all associated resources. Any descriptors or plans created with the handle become invalid and may only be destructed.
    ///
    /// Remark
    ///
    /// blocking, no reentrant, and thread-safe.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgDestroy(handle: cutensorMgHandle_t) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Create a tensor descriptor.
    ///
    /// A tensor descriptor fully specifies the data layout of a (potentially) distributed tensor. It does so mainly through five pieces of data: The extent, the element stride, the block size, the block stride, and the device count.
    ///
    /// The extent describes the total size of each tensor mode. For example, an 9 by 9 matrix would have an extent of 9 and 9.
    ///
    /// The block size describes how the data is blocked. For example, with a block size of 4 by 2, there would be three blocks in the first and five blocks in the second mode.
    ///
    /// |  |  |  |
    /// | --- | --- | --- |
    /// | 4 x 2 | 4 x 2 | 1 x 2 |
    /// | 4 x 2 | 4 x 2 | 1 x 2 |
    /// | 4 x 2 | 4 x 2 | 1 x 2 |
    /// | 4 x 2 | 4 x 2 | 1 x 2 |
    /// | 4 x 1 | 4 x 1 | 1 x 1 |
    ///
    /// The device count then describes how many devices the blocks are distributed across in that mode. A device count of 2 by 2, for example, would mean that the blocks are distributed across two devices in each mode, i.e., four devices total. The devices are aranged first along the first and then the second mode as follows:
    ///
    /// |  |  |
    /// | --- | --- |
    /// | Dev. 0 | Dev. 2 |
    /// | Dev. 1 | Dev. 3 |
    ///
    /// In particular, device 0 would own the first, and third block in the first dimension, the first, third, and fifth block in the second dimension (so a total of six blocks), device 1 would own the first and third block in the first dimension, and the second and fourth block in the second dimension (four blocks total), device 2 would own the second block in the first dimension, and the first, third, and fifth block in the second dimension (for a total of three blocks), and, finally, device 3 would own the second block in the first dimension and the second and fourth block in the second dimension (for a total of two blocks).
    ///
    /// |  |  |  |
    /// | --- | --- | --- |
    /// | Dev. 0 | Dev. 2 | Dev. 0 |
    /// | Dev. 1 | Dev. 3 | Dev. 1 |
    /// | Dev. 0 | Dev. 2 | Dev. 0 |
    /// | Dev. 1 | Dev. 3 | Dev. 1 |
    /// | Dev. 0 | Dev. 2 | Dev. 0 |
    ///
    /// The element stride and block stride then describe how the blocks are laid out on the individual devices, i.e. the distance between elements and blocks in that mode. Finally, the devices array describes which device the blocks are mapped to. Here, it is permissible to specify [`cutensorMgHostDevice_t::CUTENSOR_MG_DEVICE_HOST`] to express that those blocks are located on the host. A tensor must either be located fully on-device or fully on-host.
    ///
    /// Tensors may also be replicated, where the same tensor data is distributed across devices, or a mixture of replicated and distributed. Replication is expressed by setting numDevices to a value that is a multiple of the product of deviceCounts. At that point, the devices tensor is assumed to have an extra final mode across which the tensor is replicated. Replicated tensors can be used everywhere except as outputs for contractions. . Particularly, passing replicated tensors can unlock new optimizations that . are advantageous for problems that benefit from reduced communication.
    ///
    /// ```text
    ///  For instance, with devices = {0,1,2,3, 4,5,6,7} the tensor would be replicated
    /// ``` as follows:
    ///
    /// |  |  |  |
    /// | --- | --- | --- |
    /// | Dev. 0 & 4 | Dev. 2 & 6 | Dev. 0 & 4 |
    /// | Dev. 1 & 5 | Dev. 3 & 7 | Dev. 1 & 5 |
    /// | Dev. 0 & 4 | Dev. 2 & 6 | Dev. 0 & 4 |
    /// | Dev. 1 & 5 | Dev. 3 & 7 | Dev. 1 & 5 |
    /// | Dev. 0 & 4 | Dev. 2 & 6 | Dev. 0 & 4 |
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `desc`: The resulting tensor descriptor.
    /// - `numModes`: The number of modes.
    /// - `extent`: The extent of the tensor in each mode (array of size `numModes`).
    /// - `elementStride`: The offset (in linear memory) between two adjacent elements in each mode (array of size `numModes`), may be `NULL` for a dense tensor.
    /// - `blockSize`: The size of a block in each mode (array of size `numModes`), may be `NULL` for an unblocked tensor (i.e., each mode only has a single block that is equal to its extent).
    /// - `blockStride`: The offset (in linear memory) between two adjacent blocks in each mode (array of size `numModes`), may be `NULL` for a dense block-interleaved layout.
    /// - `deviceCount`: The number of devices that each mode is distributed across in a block-cyclic fashion (array of size `numModes`), may be `NULL` for a non-distributed tensor.
    /// - `numDevices`: The total number of devices that the tensor is distributed across (i.e., the product of all elements in `deviceCount` times how many devices it is replicated across).
    /// - `devices`: The devices that the blocks are distributed across, in column-major order, i.e., stride 1 first (array of size `numDevices`).
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: This layout or data type is not supported.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCreateTensorDescriptor(
        handle: cutensorMgHandle_t,
        desc: *mut cutensorMgTensorDescriptor_t,
        numModes: u32,
        extent: *const i64,
        elementStride: *const i64,
        blockSize: *const i64,
        blockStride: *const i64,
        deviceCount: *const i32,
        numDevices: u32,
        devices: *const i32,
        type_: cudaDataType_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Destroy a tensor descriptor.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgDestroyTensorDescriptor(
        desc: cutensorMgTensorDescriptor_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Create a copy descriptor.
    ///
    /// A copy descriptor encodes the source and the destination for a copy operation. The copy operation supports tensors on host, single, or multiple devices. It also supports layout changes and mode permutations. The only restriction is that the extents of the corresponding modes (in the input and output tensors) must match.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `desc`: The resulting copy descriptor.
    /// - `descDst`: The destination tensor descriptor.
    /// - `modesDst`: The destination tensor modes.
    /// - `descSrc`: The source tensor descriptor.
    /// - `modesSrc`: The source tensor modes.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: This tensor layout or precision combination is not supported.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCreateCopyDescriptor(
        handle: cutensorMgHandle_t,
        desc: *mut cutensorMgCopyDescriptor_t,
        descDst: cutensorMgTensorDescriptor_t,
        modesDst: *const i32,
        descSrc: cutensorMgTensorDescriptor_t,
        modesSrc: *const i32,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Destroy a copy descriptor and free all its previously-allocated resources.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgDestroyCopyDescriptor(
        desc: cutensorMgCopyDescriptor_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Computes the workspace that is needed for the copy.
    ///
    /// The function calculates the minimum workspace required for the copy operation to succeed. It returns the device workspace size in the same order as the devices are passed to the library handle.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `desc`: The copy descriptor.
    /// - `deviceWorkspaceSize`: The workspace size in bytes, for each device in the handle.
    /// - `hostWorkspaceSize`: The workspace size in bytes for pinned host memory.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCopyGetWorkspace(
        handle: cutensorMgHandle_t,
        desc: cutensorMgCopyDescriptor_t,
        deviceWorkspaceSize: *mut i64,
        hostWorkspaceSize: *mut i64,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Create a copy plan.
    ///
    /// A copy plan implements the copy operation expressed through the copy descriptor. It contains all the information needed to execute a copy operation. Planning may fail if insufficient workspace is provided.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `plan`: The resulting copy plan.
    /// - `desc`: The copy descriptor.
    /// - `deviceWorkspaceSize`: The amount of workspace that will be provided, for each device in the handle.
    /// - `hostWorkspaceSize`: The amount of pinned host workspace that will be provided.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCreateCopyPlan(
        handle: cutensorMgHandle_t,
        plan: *mut cutensorMgCopyPlan_t,
        desc: cutensorMgCopyDescriptor_t,
        deviceWorkspaceSize: *const i64,
        hostWorkspaceSize: i64,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Destroy a copy plan.
    ///
    /// When called, all outstanding operations must be completed. Frees all associated resources.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgDestroyCopyPlan(plan: cutensorMgCopyPlan_t) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Execute a copy operation.
    ///
    /// Executes a copy operation according to the given plan. It receives the source and destination pointers in the order prescribed by the `devices` parameter of the respective tensor descriptor and the device workspace and streams in the order prescribed by the `devices` parameter of the handle. If host transfers are involved in the execution the function will block until those host transfers have been completed. The function is thread safe as long as concurrent threads use different library handles.
    ///
    /// Remark
    ///
    /// calls asynchronous functions, conditionally blocking, no reentrant, and conditionally thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `plan`: The copy plan.
    /// - `ptrDst`: The destination tensor pointers.
    /// - `ptrSrc`: The source tensor pointers.
    /// - `deviceWorkspace`: The device workspace.
    /// - `hostWorkspace`: The host pinned memory workspace.
    /// - `streams`: The execution streams.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: An issue interacting with the CUDA runtime occurred.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCopy(
        handle: cutensorMgHandle_t,
        plan: cutensorMgCopyPlan_t,
        ptrDst: *mut *mut ::core::ffi::c_void,
        ptrSrc: *mut *const ::core::ffi::c_void,
        deviceWorkspace: *mut *mut ::core::ffi::c_void,
        hostWorkspace: *mut ::core::ffi::c_void,
        streams: *mut cudaStream_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Create a contraction find.
    ///
    /// The contraction find contains all the algorithmic options to execute a tensor contraction. For now, its only parameter is an algorithm, which currently only has one default value. It may gain additional options in the future.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `find`: The resulting find.
    /// - `algo`: The desired algorithm.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCreateContractionFind(
        handle: cutensorMgHandle_t,
        find: *mut cutensorMgContractionFind_t,
        algo: cutensorMgAlgo_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Destroy a contraction find.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgDestroyContractionFind(
        find: cutensorMgContractionFind_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    pub fn cutensorMgContractionFindSetAttribute(
        handle: cutensorMgHandle_t,
        find: cutensorMgContractionFind_t,
        attr: cutensorMgContractionFindAttribute_t,
        value: *const ::core::ffi::c_void,
        size: i64,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Create a contraction descriptor.
    ///
    /// A contraction descriptor encodes the operands for a contraction operation of the form:
    /// $$
    /// D = \alpha \mathcal{A} \mathcal{B} + \beta \mathcal{C}
    /// $$.
    /// The contraction operation presently supports tensors that are either on one or multiple devices, but does not support tensors stored on the host (for now). It uses the einstein notation, i.e., modes shared between only modesA and modesB are contracted. Currently, descC and descD as well as modesC and modesD must be identical. The compute type represents the lowest precision that may be used in the course of the calculation.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `desc`: The resulting tensor contraction descriptor.
    /// - `descA`: The tensor descriptor for operand A.
    /// - `modesA`: The modes for operand A.
    /// - `descB`: The tensor descriptor for operand B.
    /// - `modesB`: The modes for operand B.
    /// - `descC`: The tensor descriptor for operand C.
    /// - `modesC`: The modes for operand C.
    /// - `descD`: The tensor descriptor for operand D.
    /// - `modesD`: The modes for operand D.
    /// - `compute`: The compute type for the operation.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: This tensor layout or precision combination is not supported.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCreateContractionDescriptor(
        handle: cutensorMgHandle_t,
        desc: *mut cutensorMgContractionDescriptor_t,
        descA: cutensorMgTensorDescriptor_t,
        modesA: *const i32,
        descB: cutensorMgTensorDescriptor_t,
        modesB: *const i32,
        descC: cutensorMgTensorDescriptor_t,
        modesC: *const i32,
        descD: cutensorMgTensorDescriptor_t,
        modesD: *const i32,
        compute: cutensorComputeType_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Destroy a contraction descriptor.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgDestroyContractionDescriptor(
        desc: cutensorMgContractionDescriptor_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Computes the workspace that is needed for the contraction.
    ///
    /// The function calculates the workspace required for the contraction operation to succeed. It takes a workspace preference, which can tune how much workspace is needed. It returns the device workspace size in the same order as the devices are passed to the library handle.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `desc`: The contraction descriptor.
    /// - `find`: The contraction find.
    /// - `preference`: The workspace preference.
    /// - `deviceWorkspaceSize`: The amount of workspace in bytes, for each device in the handle.
    /// - `hostWorkspaceSize`: The amount of pinned host memory in bytes.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: This tensor layout or precision combination is not supported.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgContractionGetWorkspace(
        handle: cutensorMgHandle_t,
        desc: cutensorMgContractionDescriptor_t,
        find: cutensorMgContractionFind_t,
        preference: cutensorWorksizePreference_t,
        deviceWorkspaceSize: *mut i64,
        hostWorkspaceSize: *mut i64,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Create a contraction plan.
    ///
    /// A contraction plan implements the contraction operation expressed through the contraction descriptor in accordance to the options specified in the contraction find. It contains all the information needed to execute a contraction operation. Planning may fail if insufficient workspace is provided.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `plan`: The resulting contraction plan.
    /// - `desc`: The contraction descriptor.
    /// - `find`: The contraction find.
    /// - `deviceWorkspaceSize`: The amount of workspace in bytes, for each device in the handle.
    /// - `hostWorkspaceSize`: The amount of pinned host memory in bytes.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_NOT_SUPPORTED`]: This tensor layout or precision combination is not supported.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgCreateContractionPlan(
        handle: cutensorMgHandle_t,
        plan: *mut cutensorMgContractionPlan_t,
        desc: cutensorMgContractionDescriptor_t,
        find: cutensorMgContractionFind_t,
        deviceWorkspaceSize: *const i64,
        hostWorkspaceSize: i64,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Destroy a contraction plan.
    ///
    /// When called, all outstanding operations must be completed. Frees all associated resources.
    ///
    /// Remark
    ///
    /// non-blocking, no reentrant, and thread-safe.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgDestroyContractionPlan(
        plan: cutensorMgContractionPlan_t,
    ) -> cutensorStatus_t;
}
unsafe extern "C" {
    /// Execute a contraction operation.
    ///
    /// Executes a contraction operation according to the provided plan. It receives all the operands as arrays of pointers that are ordered according to their tensor descriptors’ `devices` parameter. The device workspace and streams are ordered according to the library handle’s `devices` parameter. The function is thread safe as long as concurrent threads use different library handles.
    ///
    /// Remark
    ///
    /// calls asynchronous functions, non-blocking, no reentrant, and conditionally thread-safe.
    ///
    /// # Parameters
    ///
    /// - `handle`: The library handle.
    /// - `plan`: The copy plan.
    /// - `alpha`: The alpha scaling factor (host pointer).
    /// - `ptrA`: The A operand tensor pointers.
    /// - `ptrB`: The B operand tensor pointers.
    /// - `beta`: The beta scaling factor (host pointer).
    /// - `ptrC`: The operand C tensor pointers.
    /// - `ptrD`: The operand D tensor pointers.
    /// - `deviceWorkspace`: The device workspace.
    /// - `hostWorkspace`: The host pinned memory workspace.
    /// - `streams`: The execution streams.
    ///
    /// # Return value
    ///
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_CUDA_ERROR`]: An issue interacting with the CUDA runtime occurred.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_INVALID_VALUE`]: Some input parameters were invalid.
    /// - [`cutensorStatus_t::CUTENSOR_STATUS_SUCCESS`]: The operation completed successfully.
    pub fn cutensorMgContraction(
        handle: cutensorMgHandle_t,
        plan: cutensorMgContractionPlan_t,
        alpha: *const ::core::ffi::c_void,
        ptrA: *mut *const ::core::ffi::c_void,
        ptrB: *mut *const ::core::ffi::c_void,
        beta: *const ::core::ffi::c_void,
        ptrC: *mut *const ::core::ffi::c_void,
        ptrD: *mut *mut ::core::ffi::c_void,
        deviceWorkspace: *mut *mut ::core::ffi::c_void,
        hostWorkspace: *mut ::core::ffi::c_void,
        streams: *mut cudaStream_t,
    ) -> cutensorStatus_t;
}