nvmath-python 1.0.0__cp314-cp314t-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. nvmath/__init__.pxd +0 -0
  2. nvmath/__init__.py +45 -0
  3. nvmath/_internal/__init__.py +0 -0
  4. nvmath/_internal/attribute_ifc_factory.py +330 -0
  5. nvmath/_internal/layout.py +70 -0
  6. nvmath/_internal/templates.py +130 -0
  7. nvmath/_internal/threadsafe.py +106 -0
  8. nvmath/_internal/utils.py +43 -0
  9. nvmath/_internal/workspace.py +490 -0
  10. nvmath/_utils.py +147 -0
  11. nvmath/bindings/__init__.py +60 -0
  12. nvmath/bindings/_internal/__init__.pxd +0 -0
  13. nvmath/bindings/_internal/__init__.py +0 -0
  14. nvmath/bindings/_internal/common_types.pxd +31 -0
  15. nvmath/bindings/_internal/cublas.cp314t-win_amd64.pyd +0 -0
  16. nvmath/bindings/_internal/cublas.pxd +530 -0
  17. nvmath/bindings/_internal/cublasLt.cp314t-win_amd64.pyd +0 -0
  18. nvmath/bindings/_internal/cublasLt.pxd +59 -0
  19. nvmath/bindings/_internal/cublasMp.pxd +52 -0
  20. nvmath/bindings/_internal/cudss.cp314t-win_amd64.pyd +0 -0
  21. nvmath/bindings/_internal/cudss.pxd +54 -0
  22. nvmath/bindings/_internal/cufft.cp314t-win_amd64.pyd +0 -0
  23. nvmath/bindings/_internal/cufft.pxd +70 -0
  24. nvmath/bindings/_internal/cufftMp.pxd +77 -0
  25. nvmath/bindings/_internal/curand.cp314t-win_amd64.pyd +0 -0
  26. nvmath/bindings/_internal/curand.pxd +42 -0
  27. nvmath/bindings/_internal/cusolver.cp314t-win_amd64.pyd +0 -0
  28. nvmath/bindings/_internal/cusolver.pxd +15 -0
  29. nvmath/bindings/_internal/cusolverDn.cp314t-win_amd64.pyd +0 -0
  30. nvmath/bindings/_internal/cusolverDn.pxd +406 -0
  31. nvmath/bindings/_internal/cusolverMp.pxd +71 -0
  32. nvmath/bindings/_internal/cusolverSp.cp314t-win_amd64.pyd +0 -0
  33. nvmath/bindings/_internal/cusolverSp.pxd +75 -0
  34. nvmath/bindings/_internal/cusparse.cp314t-win_amd64.pyd +0 -0
  35. nvmath/bindings/_internal/cusparse.pxd +471 -0
  36. nvmath/bindings/_internal/cusparseLt.cp314t-win_amd64.pyd +0 -0
  37. nvmath/bindings/_internal/cusparseLt.pxd +48 -0
  38. nvmath/bindings/_internal/cutensor.cp314t-win_amd64.pyd +0 -0
  39. nvmath/bindings/_internal/cutensor.pxd +58 -0
  40. nvmath/bindings/_internal/mathdx.cp314t-win_amd64.pyd +0 -0
  41. nvmath/bindings/_internal/mathdx.pxd +116 -0
  42. nvmath/bindings/_internal/nvshmem.pxd +29 -0
  43. nvmath/bindings/_internal/utils.cp314t-win_amd64.pyd +0 -0
  44. nvmath/bindings/_internal/utils.pxd +174 -0
  45. nvmath/bindings/_internal/utils.pyi +10 -0
  46. nvmath/bindings/cublas.cp314t-win_amd64.pyd +0 -0
  47. nvmath/bindings/cublas.pxd +558 -0
  48. nvmath/bindings/cublas.pyi +812 -0
  49. nvmath/bindings/cublasLt.cp314t-win_amd64.pyd +0 -0
  50. nvmath/bindings/cublasLt.pxd +109 -0
  51. nvmath/bindings/cublasLt.pyi +1461 -0
  52. nvmath/bindings/cublasMp.pxd +85 -0
  53. nvmath/bindings/cublasMp.pyi +267 -0
  54. nvmath/bindings/cudss.cp314t-win_amd64.pyd +0 -0
  55. nvmath/bindings/cudss.pxd +98 -0
  56. nvmath/bindings/cudss.pyi +443 -0
  57. nvmath/bindings/cufft.cp314t-win_amd64.pyd +0 -0
  58. nvmath/bindings/cufft.pxd +118 -0
  59. nvmath/bindings/cufft.pyi +301 -0
  60. nvmath/bindings/cufftMp.pxd +124 -0
  61. nvmath/bindings/cufftMp.pyi +326 -0
  62. nvmath/bindings/curand.cp314t-win_amd64.pyd +0 -0
  63. nvmath/bindings/curand.pxd +71 -0
  64. nvmath/bindings/curand.pyi +189 -0
  65. nvmath/bindings/cusolver.cp314t-win_amd64.pyd +0 -0
  66. nvmath/bindings/cusolver.pxd +62 -0
  67. nvmath/bindings/cusolver.pyi +320 -0
  68. nvmath/bindings/cusolverDn.cp314t-win_amd64.pyd +0 -0
  69. nvmath/bindings/cusolverDn.pxd +430 -0
  70. nvmath/bindings/cusolverDn.pyi +422 -0
  71. nvmath/bindings/cusolverMp.pxd +98 -0
  72. nvmath/bindings/cusolverMp.pyi +114 -0
  73. nvmath/bindings/cusolverSp.cp314t-win_amd64.pyd +0 -0
  74. nvmath/bindings/cusolverSp.pxd +95 -0
  75. nvmath/bindings/cusolverSp.pyi +70 -0
  76. nvmath/bindings/cusparse.cp314t-win_amd64.pyd +0 -0
  77. nvmath/bindings/cusparse.pxd +546 -0
  78. nvmath/bindings/cusparse.pyi +1017 -0
  79. nvmath/bindings/cusparseLt.cp314t-win_amd64.pyd +0 -0
  80. nvmath/bindings/cusparseLt.pxd +99 -0
  81. nvmath/bindings/cusparseLt.pyi +252 -0
  82. nvmath/bindings/cutensor.cp314t-win_amd64.pyd +0 -0
  83. nvmath/bindings/cutensor.pxd +98 -0
  84. nvmath/bindings/cutensor.pyi +324 -0
  85. nvmath/bindings/cycublas.cp314t-win_amd64.pyd +0 -0
  86. nvmath/bindings/cycublas.pxd +664 -0
  87. nvmath/bindings/cycublasLt.cp314t-win_amd64.pyd +0 -0
  88. nvmath/bindings/cycublasLt.pxd +1045 -0
  89. nvmath/bindings/cycublasMp.pxd +171 -0
  90. nvmath/bindings/cycudss.cp314t-win_amd64.pyd +0 -0
  91. nvmath/bindings/cycudss.pxd +277 -0
  92. nvmath/bindings/cycufft.cp314t-win_amd64.pyd +0 -0
  93. nvmath/bindings/cycufft.pxd +333 -0
  94. nvmath/bindings/cycufftMp.pxd +342 -0
  95. nvmath/bindings/cycurand.cp314t-win_amd64.pyd +0 -0
  96. nvmath/bindings/cycurand.pxd +141 -0
  97. nvmath/bindings/cycusolver.cp314t-win_amd64.pyd +0 -0
  98. nvmath/bindings/cycusolver.pxd +137 -0
  99. nvmath/bindings/cycusolverDn.cp314t-win_amd64.pyd +0 -0
  100. nvmath/bindings/cycusolverDn.pxd +443 -0
  101. nvmath/bindings/cycusolverMp.pxd +107 -0
  102. nvmath/bindings/cycusolverSp.cp314t-win_amd64.pyd +0 -0
  103. nvmath/bindings/cycusolverSp.pxd +93 -0
  104. nvmath/bindings/cycusparse.cp314t-win_amd64.pyd +0 -0
  105. nvmath/bindings/cycusparse.pxd +679 -0
  106. nvmath/bindings/cycusparseLt.cp314t-win_amd64.pyd +0 -0
  107. nvmath/bindings/cycusparseLt.pxd +135 -0
  108. nvmath/bindings/cycutensor.cp314t-win_amd64.pyd +0 -0
  109. nvmath/bindings/cycutensor.pxd +189 -0
  110. nvmath/bindings/cymathdx.cp314t-win_amd64.pyd +0 -0
  111. nvmath/bindings/cymathdx.pxd +552 -0
  112. nvmath/bindings/cynvshmem.pxd +118 -0
  113. nvmath/bindings/mathdx.cp314t-win_amd64.pyd +0 -0
  114. nvmath/bindings/mathdx.pxd +182 -0
  115. nvmath/bindings/mathdx.pyi +1562 -0
  116. nvmath/bindings/nvpl/__init__.pxd +0 -0
  117. nvmath/bindings/nvpl/__init__.py +13 -0
  118. nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
  119. nvmath/bindings/nvpl/_internal/__init__.py +0 -0
  120. nvmath/bindings/nvpl/_internal/blas.cp314t-win_amd64.pyd +0 -0
  121. nvmath/bindings/nvpl/_internal/blas.pxd +237 -0
  122. nvmath/bindings/nvpl/_internal/fft.cp314t-win_amd64.pyd +0 -0
  123. nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
  124. nvmath/bindings/nvpl/blas.cp314t-win_amd64.pyd +0 -0
  125. nvmath/bindings/nvpl/blas.pxd +131 -0
  126. nvmath/bindings/nvpl/blas.pyi +168 -0
  127. nvmath/bindings/nvpl/cyblas.cp314t-win_amd64.pyd +0 -0
  128. nvmath/bindings/nvpl/cyblas.pxd +280 -0
  129. nvmath/bindings/nvpl/cyfft.cp314t-win_amd64.pyd +0 -0
  130. nvmath/bindings/nvpl/cyfft.pxd +93 -0
  131. nvmath/bindings/nvpl/fft.cp314t-win_amd64.pyd +0 -0
  132. nvmath/bindings/nvpl/fft.pxd +100 -0
  133. nvmath/bindings/nvpl/fft.pyi +168 -0
  134. nvmath/bindings/nvshmem.pxd +54 -0
  135. nvmath/bindings/nvshmem.pyi +191 -0
  136. nvmath/device/__init__.py +38 -0
  137. nvmath/device/_deprecated.py +33 -0
  138. nvmath/device/common.py +315 -0
  139. nvmath/device/common_backend.py +131 -0
  140. nvmath/device/common_cuda.py +201 -0
  141. nvmath/device/common_numba.py +300 -0
  142. nvmath/device/common_numba_cuda_mlir.py +202 -0
  143. nvmath/device/common_opaque_tensor.py +201 -0
  144. nvmath/device/cublasdx.py +1606 -0
  145. nvmath/device/cublasdx_backend.py +860 -0
  146. nvmath/device/cublasdx_numba.py +1534 -0
  147. nvmath/device/cublasdx_numba_cuda_mlir.py +208 -0
  148. nvmath/device/cufftdx.py +373 -0
  149. nvmath/device/cufftdx_backend.py +220 -0
  150. nvmath/device/cufftdx_numba.py +140 -0
  151. nvmath/device/cufftdx_numba_cuda_mlir.py +79 -0
  152. nvmath/device/curand_kernel.py +9147 -0
  153. nvmath/device/cusolverdx.py +2708 -0
  154. nvmath/device/cusolverdx_backend.py +440 -0
  155. nvmath/device/cusolverdx_numba.py +567 -0
  156. nvmath/device/cusolverdx_numba_cuda_mlir.py +604 -0
  157. nvmath/device/cusolverdx_overload_backend.py +1029 -0
  158. nvmath/device/llvm_array.py +29 -0
  159. nvmath/device/random.py +441 -0
  160. nvmath/device/random_helpers.py +23 -0
  161. nvmath/device/random_states.py +187 -0
  162. nvmath/device/types.py +138 -0
  163. nvmath/device/vector_types_numba.py +259 -0
  164. nvmath/distributed/__init__.py +200 -0
  165. nvmath/distributed/_internal/__init__.py +0 -0
  166. nvmath/distributed/_internal/nccl.py +86 -0
  167. nvmath/distributed/_internal/nvshmem.py +307 -0
  168. nvmath/distributed/_internal/symmetric_memory.py +35 -0
  169. nvmath/distributed/_internal/tensor_ifc.py +70 -0
  170. nvmath/distributed/_internal/tensor_ifc_cupy.py +68 -0
  171. nvmath/distributed/_internal/tensor_ifc_host_device.py +172 -0
  172. nvmath/distributed/_internal/tensor_ifc_numpy.py +46 -0
  173. nvmath/distributed/_internal/tensor_ifc_torch.py +162 -0
  174. nvmath/distributed/_internal/tensor_wrapper.py +81 -0
  175. nvmath/distributed/_utils.py +167 -0
  176. nvmath/distributed/distribution/__init__.py +30 -0
  177. nvmath/distributed/distribution/_configuration.py +39 -0
  178. nvmath/distributed/distribution/distributions.py +1024 -0
  179. nvmath/distributed/distribution/redistribute.py +1284 -0
  180. nvmath/distributed/fft/__init__.py +7 -0
  181. nvmath/distributed/fft/_configuration.py +82 -0
  182. nvmath/distributed/fft/fft.py +2742 -0
  183. nvmath/distributed/linalg/__init__.py +22 -0
  184. nvmath/distributed/linalg/_internal/__init__.py +3 -0
  185. nvmath/distributed/linalg/_internal/epilog_protocol.py +586 -0
  186. nvmath/distributed/linalg/_internal/matmul_desc_ifc.py +28 -0
  187. nvmath/distributed/linalg/advanced/__init__.py +8 -0
  188. nvmath/distributed/linalg/advanced/_configuration.py +171 -0
  189. nvmath/distributed/linalg/advanced/matmulmod.py +3573 -0
  190. nvmath/distributed/linalg/generic/__init__.py +8 -0
  191. nvmath/distributed/linalg/generic/_caching.py +66 -0
  192. nvmath/distributed/linalg/generic/_configuration.py +61 -0
  193. nvmath/distributed/linalg/generic/_factorization.py +172 -0
  194. nvmath/distributed/linalg/generic/_initialization.py +966 -0
  195. nvmath/distributed/linalg/generic/_problem_spec.py +511 -0
  196. nvmath/distributed/linalg/generic/solvermod.py +1368 -0
  197. nvmath/distributed/process_group.py +408 -0
  198. nvmath/fft/__init__.py +7 -0
  199. nvmath/fft/_configuration.py +189 -0
  200. nvmath/fft/_exec_utils.py +82 -0
  201. nvmath/fft/_helpers.py +237 -0
  202. nvmath/fft/fft.py +3122 -0
  203. nvmath/internal/__init__.pxd +3 -0
  204. nvmath/internal/__init__.py +10 -0
  205. nvmath/internal/_bindings.cp314t-win_amd64.pyd +0 -0
  206. nvmath/internal/_bindings.pxd +18 -0
  207. nvmath/internal/_device_utils.py +45 -0
  208. nvmath/internal/_layout/__init__.pxd +3 -0
  209. nvmath/internal/_layout/__init__.py +7 -0
  210. nvmath/internal/_layout/_layout.cp314t-win_amd64.pyd +0 -0
  211. nvmath/internal/_layout/_layout.pxd +1303 -0
  212. nvmath/internal/_layout/_layout.pyi +1145 -0
  213. nvmath/internal/enum_utils.py +142 -0
  214. nvmath/internal/formatters.py +87 -0
  215. nvmath/internal/mem_limit.py +51 -0
  216. nvmath/internal/memory.cp314t-win_amd64.pyd +0 -0
  217. nvmath/internal/memory.pxd +13 -0
  218. nvmath/internal/memory.pyi +50 -0
  219. nvmath/internal/ndbuffer/__init__.pxd +3 -0
  220. nvmath/internal/ndbuffer/__init__.py +9 -0
  221. nvmath/internal/ndbuffer/_copy_kernel.cp314t-win_amd64.pyd +0 -0
  222. nvmath/internal/ndbuffer/_copy_kernel.pxd +10 -0
  223. nvmath/internal/ndbuffer/_jit.cp314t-win_amd64.pyd +0 -0
  224. nvmath/internal/ndbuffer/_jit.pxd +7 -0
  225. nvmath/internal/ndbuffer/_ndbuffer.cp314t-win_amd64.pyd +0 -0
  226. nvmath/internal/ndbuffer/_ndbuffer.pxd +40 -0
  227. nvmath/internal/ndbuffer/_ndbuffer.pyi +463 -0
  228. nvmath/internal/ndbuffer/copy_kernel/args.h +34 -0
  229. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/array_view.h +52 -0
  230. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/elementwise.h +68 -0
  231. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/grid_indexer.h +69 -0
  232. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/transposed.h +242 -0
  233. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/type_utils.h +39 -0
  234. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/utils.h +132 -0
  235. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/vec.h +159 -0
  236. nvmath/internal/ndbuffer/copy_kernel/elementwise.h +53 -0
  237. nvmath/internal/ndbuffer/copy_kernel/transposed.h +58 -0
  238. nvmath/internal/package_ifc.py +168 -0
  239. nvmath/internal/package_ifc_cuda.py +57 -0
  240. nvmath/internal/package_ifc_cupy.py +67 -0
  241. nvmath/internal/package_ifc_torch.py +69 -0
  242. nvmath/internal/package_wrapper.py +14 -0
  243. nvmath/internal/tensor_ifc.py +179 -0
  244. nvmath/internal/tensor_ifc_cupy.py +234 -0
  245. nvmath/internal/tensor_ifc_ndbuffer.py +147 -0
  246. nvmath/internal/tensor_ifc_numpy.py +184 -0
  247. nvmath/internal/tensor_ifc_torch.py +178 -0
  248. nvmath/internal/tensor_wrapper.py +160 -0
  249. nvmath/internal/typemaps.py +113 -0
  250. nvmath/internal/utils.py +805 -0
  251. nvmath/linalg/__init__.py +56 -0
  252. nvmath/linalg/_internal/__init__.py +3 -0
  253. nvmath/linalg/_internal/algo_cap_ifc.py +82 -0
  254. nvmath/linalg/_internal/algo_config_ifc.py +43 -0
  255. nvmath/linalg/_internal/batch.py +234 -0
  256. nvmath/linalg/_internal/enum_to_tuples.py +64 -0
  257. nvmath/linalg/_internal/epilog_protocol.py +766 -0
  258. nvmath/linalg/_internal/layout.py +624 -0
  259. nvmath/linalg/_internal/matmul_desc_ifc.py +28 -0
  260. nvmath/linalg/_internal/matmul_pref_ifc.py +27 -0
  261. nvmath/linalg/_internal/matrix_layout_ifc.py +26 -0
  262. nvmath/linalg/_internal/solver_utils.py +432 -0
  263. nvmath/linalg/_internal/typemaps.py +144 -0
  264. nvmath/linalg/_internal/utils.py +157 -0
  265. nvmath/linalg/advanced/__init__.py +8 -0
  266. nvmath/linalg/advanced/_algorithmmod.py +170 -0
  267. nvmath/linalg/advanced/_configuration.py +351 -0
  268. nvmath/linalg/advanced/helpers/__init__.py +5 -0
  269. nvmath/linalg/advanced/helpers/matmul.py +1316 -0
  270. nvmath/linalg/advanced/matmulmod.py +3734 -0
  271. nvmath/linalg/generic/__init__.py +53 -0
  272. nvmath/linalg/generic/_configuration/__init__.py +39 -0
  273. nvmath/linalg/generic/_configuration/layout.py +263 -0
  274. nvmath/linalg/generic/_configuration/match.py +734 -0
  275. nvmath/linalg/generic/_configuration/qualifiers.py +493 -0
  276. nvmath/linalg/generic/_configuration/solver_configuration.py +59 -0
  277. nvmath/linalg/generic/_configuration/wrap.py +217 -0
  278. nvmath/linalg/generic/_dtype.py +15 -0
  279. nvmath/linalg/generic/matmulmod.py +2094 -0
  280. nvmath/linalg/generic/solvermod.py +1301 -0
  281. nvmath/memory.py +279 -0
  282. nvmath/sparse/__init__.py +38 -0
  283. nvmath/sparse/_internal/__init__.py +21 -0
  284. nvmath/sparse/_internal/common_utils.py +147 -0
  285. nvmath/sparse/_internal/cudss_config_ifc.py +702 -0
  286. nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
  287. nvmath/sparse/_internal/cudss_utils.py +506 -0
  288. nvmath/sparse/_internal/cusparse_utils.py +382 -0
  289. nvmath/sparse/_internal/sparse_bsc_ifc.py +303 -0
  290. nvmath/sparse/_internal/sparse_bsr_ifc.py +305 -0
  291. nvmath/sparse/_internal/sparse_coo_ifc.py +256 -0
  292. nvmath/sparse/_internal/sparse_csc_ifc.py +268 -0
  293. nvmath/sparse/_internal/sparse_csr_ifc.py +288 -0
  294. nvmath/sparse/_internal/sparse_dia_ifc.py +242 -0
  295. nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
  296. nvmath/sparse/_internal/sparse_tensor_ifc.py +133 -0
  297. nvmath/sparse/_internal/sparse_ust_ifc.py +141 -0
  298. nvmath/sparse/_internal/utils.py +56 -0
  299. nvmath/sparse/advanced/__init__.py +7 -0
  300. nvmath/sparse/advanced/_configuration.py +227 -0
  301. nvmath/sparse/advanced/direct_solver.py +2069 -0
  302. nvmath/sparse/generic/__init__.py +7 -0
  303. nvmath/sparse/generic/_configuration.py +129 -0
  304. nvmath/sparse/generic/_helpers.py +137 -0
  305. nvmath/sparse/generic/_thunks.py +21 -0
  306. nvmath/sparse/generic/matmulmod.py +2353 -0
  307. nvmath/sparse/ust/__init__.py +7 -0
  308. nvmath/sparse/ust/_converters.py +422 -0
  309. nvmath/sparse/ust/_cpp.py +28 -0
  310. nvmath/sparse/ust/_drawer.py +565 -0
  311. nvmath/sparse/ust/_emitter.py +1033 -0
  312. nvmath/sparse/ust/_jit.py +188 -0
  313. nvmath/sparse/ust/_kernel.py +282 -0
  314. nvmath/sparse/ust/_utils.py +149 -0
  315. nvmath/sparse/ust/interfaces/__init__.py +0 -0
  316. nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
  317. nvmath/sparse/ust/tensor.py +1016 -0
  318. nvmath/sparse/ust/tensor_format.py +957 -0
  319. nvmath/tensor/__init__.py +6 -0
  320. nvmath/tensor/_configuration.py +120 -0
  321. nvmath/tensor/_internal/__init__.py +3 -0
  322. nvmath/tensor/_internal/cutensor_config_ifc.py +279 -0
  323. nvmath/tensor/_internal/cutensor_utils.py +230 -0
  324. nvmath/tensor/_internal/data.py +43 -0
  325. nvmath/tensor/_internal/einsum_parser.py +444 -0
  326. nvmath/tensor/_internal/typemaps.py +96 -0
  327. nvmath/tensor/contract.py +1900 -0
  328. nvmath_python-1.0.0.dist-info/METADATA +134 -0
  329. nvmath_python-1.0.0.dist-info/RECORD +332 -0
  330. nvmath_python-1.0.0.dist-info/WHEEL +5 -0
  331. nvmath_python-1.0.0.dist-info/licenses/LICENSE +177 -0
  332. nvmath_python-1.0.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,766 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """Internal interface for epilog input handling."""
6
+
7
+ __all__ = [
8
+ "EPILOG_INPUT_HANDLERS_MAP",
9
+ "EPILOG_OUTPUT_HANDLERS_MAP",
10
+ "BiasHandler",
11
+ "BgradHandler",
12
+ "ReluAuxHandler",
13
+ "DReluAuxHandler",
14
+ "GeluAuxHandler",
15
+ "DGeluAuxHandler",
16
+ "EpilogInputHandler",
17
+ "EpilogOutputHandler",
18
+ ]
19
+
20
+ import math
21
+ from abc import abstractmethod
22
+ from typing import Protocol, runtime_checkable
23
+
24
+ from nvmath.bindings import cublasLt as cublaslt
25
+ from nvmath.internal import typemaps
26
+ from nvmath.linalg._internal.utils import axis_order_in_memory, calculate_strides, check_batch_tileable
27
+
28
+ Epilog = cublaslt.Epilogue
29
+
30
+
31
+ @runtime_checkable
32
+ class EpilogInputHandler(Protocol):
33
+ """
34
+ Protocol for epilog handler input validation and setting the appropriate MM descriptor
35
+ attributes.
36
+ """
37
+
38
+ @abstractmethod
39
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
40
+ raise NotImplementedError
41
+
42
+ @property
43
+ @abstractmethod
44
+ def name(self):
45
+ """
46
+ The name of the epilog input that is handled (bias, ...).
47
+ """
48
+ raise NotImplementedError
49
+
50
+ @property
51
+ @abstractmethod
52
+ def order(self) -> cublaslt.Order | None:
53
+ """
54
+ The result order that is needed by this epilog (cublaslt.Order or None, if no
55
+ restriction on order).
56
+ """
57
+ raise NotImplementedError
58
+
59
+ @abstractmethod
60
+ def validate(self, epilog_input):
61
+ """
62
+ Validate the provided epilog input.
63
+
64
+ Args:
65
+ epilog_input: The epilog input to validate.
66
+
67
+ """
68
+ raise NotImplementedError
69
+
70
+ @abstractmethod
71
+ def update(self, mm_desc_ifc, epilog_input):
72
+ """
73
+ Update the matmul descriptor attributes for this epilog from the given input.
74
+
75
+ Args:
76
+ mm_desc_ifc: The MM descriptor to update, provided as
77
+ a MatmulDescInterface object.
78
+ epilog_input: The epilog input.
79
+ """
80
+ raise NotImplementedError
81
+
82
+ @abstractmethod
83
+ def update_pointer(self, mm_desc_ifc, data_ptr) -> None:
84
+ """
85
+ Update the matmul descriptor data pointer for this epilog.
86
+
87
+ Unlike ``update``, this only sets the pointer, assuming all other
88
+ descriptor attributes (batch stride, leading dimension, data type)
89
+ are already valid.
90
+
91
+ Args:
92
+ mm_desc_ifc: The MM descriptor to update, provided
93
+ as a MatmulDescInterface object.
94
+ data_ptr: The device pointer value to set.
95
+ """
96
+ raise NotImplementedError
97
+
98
+
99
+ @runtime_checkable
100
+ class EpilogOutputHandler(Protocol):
101
+ """
102
+ Protocol for epilog handler output validation and setting the appropriate MM descriptor
103
+ attributes.
104
+ """
105
+
106
+ @abstractmethod
107
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
108
+ raise NotImplementedError
109
+
110
+ @property
111
+ @abstractmethod
112
+ def name(self):
113
+ """
114
+ The name of the epilog output that is handled (relu_aux, gelu_aux, bgrad, bragda,
115
+ bgradb, ...).
116
+ """
117
+ raise NotImplementedError
118
+
119
+ @property
120
+ @abstractmethod
121
+ def order(self):
122
+ """
123
+ The result order that is needed by this epilog (cublaslt.Order or None, if no
124
+ restriction on order).
125
+ """
126
+ raise NotImplementedError
127
+
128
+ @abstractmethod
129
+ def attributes(self):
130
+ """
131
+ The shape, stride, and dtype name of the output tensor.
132
+ """
133
+ raise NotImplementedError
134
+
135
+ @abstractmethod
136
+ def update(self, mm_desc_ifc):
137
+ """
138
+ Update all the attributes for this epilog, except the pointer.
139
+
140
+ Args:
141
+ mm_desc_ifc: The MM descriptor to update, provided as a MatmulDescInterface
142
+ object.
143
+ """
144
+ raise NotImplementedError
145
+
146
+ @abstractmethod
147
+ def update_pointer(self, mm_desc_ifc, ptr):
148
+ """
149
+ Set the pointer for this epilog.
150
+
151
+ Args:
152
+ mm_desc_ifc: The MM descriptor to update, provided as a MatmulDescInterface
153
+ object.
154
+
155
+ ptr: The pointer to set.
156
+
157
+ """
158
+ raise NotImplementedError
159
+
160
+
161
+ class BiasHandler(EpilogInputHandler):
162
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
163
+ self.logger = logger
164
+ self.mm_traits = mm_traits
165
+
166
+ assert enumerator in [
167
+ Epilog.BIAS,
168
+ Epilog.RELU_BIAS,
169
+ Epilog.RELU_AUX_BIAS,
170
+ Epilog.GELU_BIAS,
171
+ Epilog.GELU_AUX_BIAS,
172
+ ], "Internal error."
173
+ self.enumerator = enumerator
174
+
175
+ self.d_dtype_name = d_dtype_name
176
+
177
+ self.batch_offset = None
178
+
179
+ self._name = "bias"
180
+
181
+ self.version = cublaslt.get_version()
182
+
183
+ @property
184
+ def name(self):
185
+ return self._name
186
+
187
+ @property
188
+ def order(self):
189
+ return cublaslt.Order.COL
190
+
191
+ def validate(self, bias_tensor):
192
+ # The bias_tensor must be of rank 1, or rank 2 with (M, 1) or batched versions of
193
+ # the latter (..., M, 1) consistent with the C operand.
194
+
195
+ bias_shape = list(bias_tensor.shape)
196
+ bias_strides = list(bias_tensor.strides)
197
+
198
+ mm_traits = self.mm_traits
199
+
200
+ # Determine the rank of bias_tensor input.
201
+ bias_batch_shape, bias_mm_shape = bias_shape[:-2], bias_shape[-2:]
202
+ bias_batch_strides, bias_mm_strides = bias_strides[:-2], bias_strides[-2:]
203
+ if len(bias_mm_shape) == 1:
204
+ s, d = bias_mm_shape[0], bias_mm_strides[0]
205
+ bias_mm_shape += [1]
206
+ bias_mm_strides += [s * d]
207
+ self.logger.debug(f"The MM shape for the bias is {bias_mm_shape} with strides {bias_mm_strides}.")
208
+
209
+ Mb, Nb = bias_mm_shape
210
+ if Mb != mm_traits.M:
211
+ raise ValueError(f"The M dimension of the bias vector ({Mb}) must match the M dimension of A.")
212
+
213
+ if Nb != 1:
214
+ raise ValueError(f"The N dimension of the bias vector ({Nb}) must be equal to 1.")
215
+
216
+ # Check if the bias_tensor batch shape and axis order match that of the MM, and it's
217
+ # tileable.
218
+ if len(bias_batch_shape) > 0 and bias_batch_shape != mm_traits.batch_shape:
219
+ raise ValueError(
220
+ f"The batch dimensions of the bias {bias_batch_shape} must match with that of the matrix multiplication "
221
+ f"definition {mm_traits.batch_shape}."
222
+ )
223
+
224
+ if self.version < 110902 and len(bias_batch_shape) == 0 and len(mm_traits.batch_shape) > 0:
225
+ raise ValueError(
226
+ f"Bias broadcasting is not supported in cuBLASLt version < 110902 (you have version {self.version})."
227
+ )
228
+
229
+ if len(bias_batch_shape) > 0:
230
+ if self.version < 11703:
231
+ raise ValueError(
232
+ f"Batch dimensions are not supported for the bias tensor in cuBLASLt version < 11703 "
233
+ f"(you have version {self.version})."
234
+ )
235
+
236
+ bias_batch_axis_order = axis_order_in_memory(bias_batch_strides)
237
+ if bias_batch_axis_order != mm_traits.batch_axis_order:
238
+ raise ValueError(
239
+ f"The batch axis order of the bias {bias_batch_axis_order} must match with that "
240
+ f"of the other operands {mm_traits.batch_axis_order}."
241
+ )
242
+
243
+ if not check_batch_tileable(bias_batch_shape, bias_batch_strides):
244
+ message = (
245
+ f"The batch layout for bias corresponding to shape = {bias_batch_shape} "
246
+ f"and strides = {bias_batch_strides} is currently not supported because it is not tileable."
247
+ )
248
+ raise ValueError(message)
249
+
250
+ if bias_mm_strides[0] != 1:
251
+ raise ValueError(
252
+ f"The stride of the bias {bias_strides} must be 1 along the dimension {len(bias_strides) - 2}, "
253
+ f"which corresponds to the M dimension."
254
+ )
255
+
256
+ self.batch_offset = min(bias_batch_strides) if bias_batch_strides else 0 # bias broadcast
257
+
258
+ def update_pointer(self, mm_desc_ifc, data_ptr):
259
+ mm_desc_ifc.bias_pointer = data_ptr
260
+
261
+ def update(self, mm_desc_ifc, bias_tensor):
262
+ # Set the bias pointer.
263
+ mm_desc_ifc.bias_pointer = bias_tensor.data_ptr
264
+ # Set the bias batch offset.
265
+ mm_desc_ifc.bias_batch_stride = self.batch_offset
266
+ # Set the bias data type.
267
+ if bias_tensor.dtype != self.d_dtype_name:
268
+ if self.version < 111103:
269
+ raise ValueError(
270
+ f"The bias tensor dtype '{bias_tensor.dtype}' must be the same as the result dtype "
271
+ f"'{self.d_dtype_name}' in cuBLASLt version < 111103 (you have {self.version})."
272
+ )
273
+ mm_desc_ifc.bias_data_type = typemaps.NAME_TO_DATA_TYPE[bias_tensor.dtype]
274
+
275
+
276
+ def round_up(m, base):
277
+ return m + (base - m) % base
278
+
279
+
280
+ def relu_aux_mm_shape(m, n):
281
+ """
282
+ Return the RELU auxiliary bitmask matrix shape when stored as uint8 and M is padded to
283
+ 128-bit/16-byte multiples.
284
+ """
285
+ # Store bitflag mask using int8 dtype, padded to (128//8 ==) 16 bytes.
286
+ m = round_up(math.ceil(m / 8), base=16)
287
+ return m, n
288
+
289
+
290
+ def gelu_aux_mm_shape(m, n):
291
+ """
292
+ Return the GELU auxiliary matrix shape when M is padded to 8-byte multiples.
293
+ """
294
+ m = round_up(m, base=8)
295
+ return m, n
296
+
297
+
298
+ class ReluAuxHandler(EpilogOutputHandler):
299
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
300
+ self.logger = logger
301
+ self.mm_traits = mm_traits
302
+
303
+ assert enumerator in [Epilog.RELU_AUX, Epilog.RELU_AUX_BIAS], "Internal error."
304
+ self.enumerator = enumerator
305
+
306
+ self._name = "relu_aux"
307
+
308
+ m, n = relu_aux_mm_shape(mm_traits.M, mm_traits.N)
309
+ batch_len = len(mm_traits.batch_axis_order)
310
+
311
+ self.aux_shape = mm_traits.batch_shape + [m, n]
312
+ aux_axis_order = [batch_len, batch_len + 1] + list(mm_traits.batch_axis_order) # Column order for the bitmask.
313
+ self.aux_strides = calculate_strides(self.aux_shape, aux_axis_order)
314
+ if aux_dtype_name is not None:
315
+ raise ValueError("Custom type for auxiliary outputs is not supported for RELU epilogs.")
316
+ self.aux_dtype_name = "uint8"
317
+
318
+ # We store bitmask using int8 dtype but the values below are in number of elements.
319
+ self.aux_ld = m * 8 # should be consistent with order (currently COL).
320
+ self.aux_batch_offset = m * 8 * n
321
+
322
+ @property
323
+ def name(self):
324
+ return self._name
325
+
326
+ @property
327
+ def order(self):
328
+ return cublaslt.Order.COL
329
+
330
+ def attributes(self):
331
+ return self.aux_shape, self.aux_strides, self.aux_dtype_name
332
+
333
+ def update(self, mm_desc_ifc):
334
+ # Set the aux LD.
335
+ mm_desc_ifc.epilogue_aux_ld = self.aux_ld
336
+ # Set the aux batch offset.
337
+ mm_desc_ifc.epilogue_aux_batch_stride = self.aux_batch_offset
338
+ # Set the pointer to 0x1 to bypass the cuBLAS check.
339
+ mm_desc_ifc.epilogue_aux_pointer = 0x1
340
+
341
+ def update_pointer(self, mm_desc_ifc, ptr):
342
+ # Set the aux pointer.
343
+ mm_desc_ifc.epilogue_aux_pointer = ptr
344
+
345
+
346
+ class GeluAuxHandler(EpilogOutputHandler):
347
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
348
+ self.logger = logger
349
+ self.mm_traits = mm_traits
350
+
351
+ assert enumerator in [Epilog.GELU_AUX, Epilog.GELU_AUX_BIAS], "Internal error."
352
+ self.enumerator = enumerator
353
+
354
+ self.d_dtype_name = d_dtype_name
355
+
356
+ self._name = "gelu_aux"
357
+
358
+ m, n = gelu_aux_mm_shape(mm_traits.M, mm_traits.N)
359
+ batch_len = len(mm_traits.batch_axis_order)
360
+
361
+ self.aux_shape = mm_traits.batch_shape + [m, n]
362
+ aux_axis_order = [batch_len, batch_len + 1] + list(mm_traits.batch_axis_order) # Column order for the GELU inputs.
363
+ self.aux_strides = calculate_strides(self.aux_shape, aux_axis_order)
364
+
365
+ self.version = cublaslt.get_version()
366
+
367
+ if aux_dtype_name:
368
+ if self.version < 120800:
369
+ raise ValueError("Specifying custom AUX data type is not supported for cuBLAS < 12.8.")
370
+ self.aux_dtype_name = aux_dtype_name
371
+ else:
372
+ self.aux_dtype_name = c_dtype_name if "float8" in d_dtype_name else d_dtype_name
373
+
374
+ self.aux_ld = m # should be consistent with order (currently COL).
375
+ self.aux_batch_offset = m * n
376
+
377
+ @property
378
+ def name(self):
379
+ return self._name
380
+
381
+ @property
382
+ def order(self):
383
+ return cublaslt.Order.COL
384
+
385
+ def attributes(self):
386
+ return self.aux_shape, self.aux_strides, self.aux_dtype_name
387
+
388
+ def update(self, mm_desc_ifc):
389
+ # Set the aux LD.
390
+ mm_desc_ifc.epilogue_aux_ld = self.aux_ld
391
+ # Set the aux batch offset.
392
+ mm_desc_ifc.epilogue_aux_batch_stride = self.aux_batch_offset
393
+ # Set the pointer to 0x1 to bypass the cuBLAS check.
394
+ mm_desc_ifc.epilogue_aux_pointer = 0x1
395
+ if self.aux_dtype_name is not None and self.version >= 120800:
396
+ mm_desc_ifc.epilogue_aux_data_type = typemaps.NAME_TO_DATA_TYPE[self.aux_dtype_name]
397
+
398
+ def update_pointer(self, mm_desc_ifc, ptr):
399
+ # Set the aux pointer.
400
+ mm_desc_ifc.epilogue_aux_pointer = ptr
401
+
402
+
403
+ class BgradHandler(EpilogOutputHandler):
404
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
405
+ self.logger = logger
406
+ self.mm_traits = mm_traits
407
+
408
+ assert enumerator in [Epilog.DRELU_BGRAD, Epilog.DGELU_BGRAD, Epilog.BGRADA, Epilog.BGRADB], "Internal error."
409
+ self.enumerator = enumerator
410
+
411
+ version = cublaslt.get_version()
412
+ if mm_traits.K == 1 and enumerator in [Epilog.BGRADA, Epilog.BGRADB] and version < 120304:
413
+ raise ValueError(
414
+ f"K=1 is not supported for {enumerator.name} epilog in cuBLASLt version < 120304 (you have version {version})."
415
+ )
416
+
417
+ self._name = enumerator.name.lower()
418
+
419
+ if aux_dtype_name is not None:
420
+ raise ValueError("Custom type for auxiliary outputs is not supported for BGRAD epilogs.")
421
+
422
+ m = mm_traits.N if enumerator == Epilog.BGRADB else mm_traits.M
423
+ batch_len = len(mm_traits.batch_axis_order)
424
+
425
+ self.bgrad_shape = shape = [m]
426
+ if mm_traits.batch_shape:
427
+ shape = shape + [1]
428
+ self.bgrad_shape = mm_traits.batch_shape + self.bgrad_shape + [1]
429
+
430
+ bgrad_axis_order = [batch_len + a for a in range(len(shape))] + list(mm_traits.batch_axis_order) # Column order.
431
+ self.bgrad_strides = calculate_strides(self.bgrad_shape, bgrad_axis_order)
432
+
433
+ self.d_dtype_name = d_dtype_name
434
+ self.bgrad_dtype_name = d_dtype_name
435
+ self.bgrad_batch_offset = m
436
+
437
+ @property
438
+ def name(self):
439
+ return self._name
440
+
441
+ @property
442
+ def order(self):
443
+ """
444
+ For BGRADA or BGRADB, there is no layout constraint but DRELU_BGRAD and DGELU_BGRAD
445
+ require COL. However currently use COL for BGRADB as well to workaround a library
446
+ issue.
447
+ """
448
+ if self.enumerator in [Epilog.DRELU_BGRAD, Epilog.DGELU_BGRAD, Epilog.BGRADB]:
449
+ return cublaslt.Order.COL
450
+ return None
451
+
452
+ def attributes(self):
453
+ return self.bgrad_shape, self.bgrad_strides, self.bgrad_dtype_name
454
+
455
+ def update(self, mm_desc_ifc):
456
+ # Set the bgrad batch offset.
457
+ mm_desc_ifc.bias_batch_stride = self.bgrad_batch_offset
458
+ # The bgrad data type is by default the data type of the result for all the cases we
459
+ # support.
460
+ assert self.bgrad_dtype_name == self.d_dtype_name, "Internal error."
461
+
462
+ def update_pointer(self, mm_desc_ifc, ptr):
463
+ # Set the bgrad pointer.
464
+ mm_desc_ifc.bias_pointer = ptr
465
+
466
+
467
+ class DReluAuxHandler(EpilogInputHandler):
468
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
469
+ self.logger = logger
470
+ self.mm_traits = mm_traits
471
+
472
+ assert enumerator in [Epilog.DRELU, Epilog.DRELU_BGRAD], "Internal error."
473
+ self.enumerator = enumerator
474
+
475
+ self.batch_offset = None
476
+
477
+ self._name = "relu_aux"
478
+
479
+ # The bitmask int8 matrix shape, including padding.
480
+ self.mm_m, self.mm_n = relu_aux_mm_shape(mm_traits.M, mm_traits.N)
481
+
482
+ # We store bitmask using int8 dtype but the values below are in number of elements.
483
+ self.aux_ld = self.mm_m * 8 # should be consistent with order (currently COL).
484
+
485
+ # K=1 is not supported by cuBLAS
486
+ if mm_traits.K == 1:
487
+ raise ValueError("K=1 is not supported for DRELU epilogs")
488
+
489
+ @property
490
+ def name(self):
491
+ return self._name
492
+
493
+ @property
494
+ def order(self):
495
+ return cublaslt.Order.COL
496
+
497
+ def validate(self, relu_aux_tensor):
498
+ # The relu_aux_tensor must be of rank 2 or its batched version of the latter (...,
499
+ # M, N).
500
+ relu_aux_shape = list(relu_aux_tensor.shape)
501
+ relu_aux_strides = list(relu_aux_tensor.strides)
502
+
503
+ # The dtype must be uint8.
504
+ if relu_aux_tensor.dtype != "uint8":
505
+ raise ValueError(
506
+ f"The dtype of the RELU auxiliary input for epilog {self.enumerator.name} must be 'uint8'. "
507
+ f"The epilog input's dtype is '{relu_aux_tensor.dtype}'."
508
+ )
509
+
510
+ mm_traits = self.mm_traits
511
+
512
+ # Determine the rank of relu_aux_tensor input.
513
+ relu_aux_batch_shape, relu_aux_mm_shape = relu_aux_shape[:-2], relu_aux_shape[-2:]
514
+ relu_aux_batch_strides, relu_aux_mm_strides = relu_aux_strides[:-2], relu_aux_strides[-2:]
515
+
516
+ # The MM shape must match, the MM must be in col order, and the batch order must
517
+ # match.
518
+ Ma, Na = relu_aux_mm_shape
519
+ if Ma != self.mm_m or Na != self.mm_n:
520
+ raise ValueError(
521
+ f"The auxiliary epilog input for epilog {self.enumerator.name} must have the MM shape "
522
+ f"(..., {self.mm_m}, {self.mm_n}). The epilog input's MM shape is (..., {Ma}, {Na})."
523
+ )
524
+
525
+ # Check if the relu_aux_tensor batch shape and axis order match that of the MM, and
526
+ # it's tileable.
527
+ if len(relu_aux_batch_shape) > 0:
528
+ if relu_aux_batch_shape != mm_traits.batch_shape:
529
+ raise ValueError(
530
+ f"The batch dimensions of the RELU auxiliary input {relu_aux_batch_shape} must match with that "
531
+ f"of the matrix multiplication definition {mm_traits.batch_shape}."
532
+ )
533
+
534
+ if (relu_aux_batch_axis_order := axis_order_in_memory(relu_aux_batch_strides)) != mm_traits.batch_axis_order:
535
+ raise ValueError(
536
+ f"The batch axis order of the RELU auxiliary input {relu_aux_batch_axis_order} must match with that "
537
+ f"of the other operands {mm_traits.batch_axis_order}."
538
+ )
539
+
540
+ if not check_batch_tileable(relu_aux_batch_shape, relu_aux_batch_strides):
541
+ message = (
542
+ f"The batch layout for RELU auxiliary input corresponding to shape = {relu_aux_batch_shape} "
543
+ f"and strides = {relu_aux_batch_strides} is currently not supported because it is not tileable."
544
+ )
545
+ raise ValueError(message)
546
+
547
+ if relu_aux_mm_strides[0] != 1:
548
+ raise ValueError(
549
+ f"The stride of the RELU auxiliary input {relu_aux_strides} must be 1 "
550
+ f"along the dimension {len(relu_aux_strides) - 2}, which corresponds to the M dimension."
551
+ )
552
+
553
+ # Convert from bits to elements.
554
+ self.batch_offset = min(relu_aux_batch_strides) * 8 if relu_aux_batch_strides else 0 # relu_aux broadcast
555
+
556
+ if self.batch_offset > 0:
557
+ assert self.batch_offset >= self.mm_m * 8 * self.mm_n, "Tensor data must not overlap."
558
+
559
+ def update_pointer(self, mm_desc_ifc, data_ptr):
560
+ mm_desc_ifc.epilogue_aux_pointer = data_ptr
561
+
562
+ def update(self, mm_desc_ifc, relu_aux_tensor):
563
+ # Set the epilog aux pointer.
564
+ mm_desc_ifc.epilogue_aux_pointer = relu_aux_tensor.data_ptr
565
+ # Set the relu_aux batch offset.
566
+ mm_desc_ifc.epilogue_aux_batch_stride = self.batch_offset
567
+ # Set the aux LD.
568
+ mm_desc_ifc.epilogue_aux_ld = self.aux_ld
569
+ # The relu aux data type is bitmask, don't set.
570
+
571
+
572
+ class DGeluAuxHandler(EpilogInputHandler):
573
+ def __init__(self, logger, mm_traits, enumerator, c_dtype_name, d_dtype_name, aux_dtype_name):
574
+ self.logger = logger
575
+ self.mm_traits = mm_traits
576
+
577
+ assert enumerator in [Epilog.DGELU, Epilog.DGELU_BGRAD], "Internal error."
578
+ self.enumerator = enumerator
579
+
580
+ self.d_dtype_name = d_dtype_name
581
+
582
+ self.batch_offset = None
583
+
584
+ self._name = "gelu_aux"
585
+
586
+ # The GELU aux matrix shape, including padding.
587
+ self.mm_m, self.mm_n = gelu_aux_mm_shape(mm_traits.M, mm_traits.N)
588
+
589
+ self.aux_ld = self.mm_m # should be consistent with order (currently COL).
590
+
591
+ self.version = cublaslt.get_version()
592
+
593
+ # K=1 is not supported by cuBLAS
594
+ if mm_traits.K == 1:
595
+ raise ValueError("K=1 is not supported for DGELU epilogs")
596
+
597
+ @property
598
+ def name(self):
599
+ return self._name
600
+
601
+ @property
602
+ def order(self):
603
+ return cublaslt.Order.COL
604
+
605
+ def validate(self, gelu_aux_tensor):
606
+ # The gelu_aux_tensor must be of rank 2 or its batched version of the latter (...,
607
+ # M, N).
608
+ gelu_aux_shape = list(gelu_aux_tensor.shape)
609
+ gelu_aux_strides = list(gelu_aux_tensor.strides)
610
+
611
+ # The dtype must be the same as that of D.
612
+ if gelu_aux_tensor.dtype != self.d_dtype_name:
613
+ raise ValueError(
614
+ f"The dtype of the GELU auxiliary input for epilog {self.enumerator.name} must be '{self.d_dtype_name}'. "
615
+ f"The epilog input's dtype is '{gelu_aux_tensor.dtype}'."
616
+ )
617
+
618
+ mm_traits = self.mm_traits
619
+
620
+ # Determine the rank of gelu_aux_tensor input.
621
+ gelu_aux_batch_shape, gelu_aux_mm_shape = gelu_aux_shape[:-2], gelu_aux_shape[-2:]
622
+ gelu_aux_batch_strides, gelu_aux_mm_strides = gelu_aux_strides[:-2], gelu_aux_strides[-2:]
623
+
624
+ # The MM shape must match, the MM must be in col order, and the batch order must
625
+ # match.
626
+ Ma, Na = gelu_aux_mm_shape
627
+ if Ma != self.mm_m or Na != self.mm_n:
628
+ raise ValueError(
629
+ f"The auxiliary epilog input for epilog {self.enumerator.name} must have "
630
+ f"the MM shape (..., {self.mm_m}, {self.mm_n}). The epilog input's MM shape is (..., {Ma}, {Na})."
631
+ )
632
+
633
+ # Check if the gelu_aux_tensor batch shape and axis order match that of the MM, and
634
+ # it's tileable.
635
+ if len(gelu_aux_batch_shape) > 0:
636
+ if gelu_aux_batch_shape != mm_traits.batch_shape:
637
+ raise ValueError(
638
+ f"The batch dimensions of the GELU auxiliary input {gelu_aux_batch_shape} must match with that "
639
+ f"of the matrix multiplication definition {mm_traits.batch_shape}."
640
+ )
641
+
642
+ if (gelu_aux_batch_axis_order := axis_order_in_memory(gelu_aux_batch_strides)) != mm_traits.batch_axis_order:
643
+ raise ValueError(
644
+ f"The batch axis order of the GELU auxiliary input {gelu_aux_batch_axis_order} "
645
+ f"must match with that of the other operands {mm_traits.batch_axis_order}."
646
+ )
647
+
648
+ if not check_batch_tileable(gelu_aux_batch_shape, gelu_aux_batch_strides):
649
+ message = (
650
+ f"The batch layout for GELU auxiliary input corresponding to shape = {gelu_aux_batch_shape} and "
651
+ f"strides = {gelu_aux_batch_strides} is currently not supported because it is not tileable."
652
+ )
653
+ raise ValueError(message)
654
+
655
+ if gelu_aux_mm_strides[0] != 1:
656
+ raise ValueError(
657
+ f"The stride of the GELU auxiliary input {gelu_aux_strides} must be 1 "
658
+ f"along the dimension {len(gelu_aux_strides) - 2}, which corresponds to the M dimension."
659
+ )
660
+
661
+ self.batch_offset = min(gelu_aux_batch_strides) if gelu_aux_batch_strides else 0 # gelu_aux broadcast
662
+
663
+ if self.batch_offset > 0:
664
+ assert self.batch_offset >= self.mm_m * self.mm_n, "Tensor data must not overlap."
665
+
666
+ def update_pointer(self, mm_desc_ifc, data_ptr):
667
+ mm_desc_ifc.epilogue_aux_pointer = data_ptr
668
+
669
+ def update(self, mm_desc_ifc, gelu_aux_tensor):
670
+ # Set the epilog aux pointer.
671
+ mm_desc_ifc.epilogue_aux_pointer = gelu_aux_tensor.data_ptr
672
+ # Set the gelu_aux batch offset.
673
+ mm_desc_ifc.epilogue_aux_batch_stride = self.batch_offset
674
+ # Set the aux LD.
675
+ mm_desc_ifc.epilogue_aux_ld = self.aux_ld
676
+ # Set the gelu aux data type.
677
+ if gelu_aux_tensor.dtype != self.d_dtype_name:
678
+ if self.version < 111103:
679
+ raise ValueError(
680
+ f"The GELU auxiliary tensor dtype '{gelu_aux_tensor.dtype}' must be the same as "
681
+ f"the result dtype '{self.d_dtype_name}' in cuBLASLt version < 111103 (you have {self.version})."
682
+ )
683
+ mm_desc_ifc.epilogue_aux_data_type = typemaps.NAME_TO_DATA_TYPE[gelu_aux_tensor.dtype]
684
+
685
+
686
+ EPILOG_INPUT_HANDLERS_MAP: dict[cublaslt.Epilogue, list[type[EpilogInputHandler]]] = {
687
+ Epilog.RELU: [],
688
+ Epilog.RELU_AUX: [],
689
+ Epilog.GELU: [],
690
+ Epilog.GELU_AUX: [],
691
+ Epilog.BIAS: [BiasHandler],
692
+ Epilog.RELU_BIAS: [BiasHandler],
693
+ Epilog.RELU_AUX_BIAS: [BiasHandler],
694
+ Epilog.GELU_BIAS: [BiasHandler],
695
+ Epilog.GELU_AUX_BIAS: [BiasHandler],
696
+ Epilog.DRELU: [DReluAuxHandler],
697
+ Epilog.DRELU_BGRAD: [DReluAuxHandler],
698
+ Epilog.DGELU: [DGeluAuxHandler],
699
+ Epilog.DGELU_BGRAD: [DGeluAuxHandler],
700
+ Epilog.BGRADA: [],
701
+ Epilog.BGRADB: [],
702
+ }
703
+
704
+ EPILOG_OUTPUT_HANDLERS_MAP: dict[cublaslt.Epilogue, list[type[EpilogOutputHandler]]] = {
705
+ Epilog.RELU: [],
706
+ Epilog.RELU_AUX: [ReluAuxHandler],
707
+ Epilog.GELU: [],
708
+ Epilog.GELU_AUX: [GeluAuxHandler],
709
+ Epilog.BIAS: [],
710
+ Epilog.RELU_BIAS: [],
711
+ Epilog.RELU_AUX_BIAS: [ReluAuxHandler],
712
+ Epilog.GELU_BIAS: [],
713
+ Epilog.GELU_AUX_BIAS: [GeluAuxHandler],
714
+ Epilog.DRELU: [],
715
+ Epilog.DRELU_BGRAD: [BgradHandler],
716
+ Epilog.DGELU: [],
717
+ Epilog.DGELU_BGRAD: [BgradHandler],
718
+ Epilog.BGRADA: [BgradHandler],
719
+ Epilog.BGRADB: [BgradHandler],
720
+ }
721
+
722
+ EPILOG_MINIMUM_VERSIONS_MAP: dict[cublaslt.Epilogue | None, dict[str, int | str]] = {
723
+ None: {"cublaslt": 00000, "ctk": ""},
724
+ # RELU was the first implemented epilog
725
+ Epilog.RELU: {"cublaslt": 11000, "ctk": "11.0.1"},
726
+ # 11301, 11.2.0 supports ^
727
+ # 11401, 11.2.2 supports ^
728
+ # 11402, 11.3.0 supports ^
729
+ # Even though some *BIAS epilogs appear in earlier headers, because
730
+ # CUBLASLT_MATMUL_DESC_BIAS_BATCH_STRIDE is not defined we cannot use them.
731
+ Epilog.GELU: {"cublaslt": 11501, "ctk": "11.3.1"},
732
+ Epilog.BIAS: {"cublaslt": 11501, "ctk": "11.3.1"},
733
+ Epilog.RELU_AUX: {"cublaslt": 11501, "ctk": "11.3.1"},
734
+ Epilog.GELU_AUX: {"cublaslt": 11501, "ctk": "11.3.1"},
735
+ Epilog.RELU_BIAS: {"cublaslt": 11501, "ctk": "11.3.1"},
736
+ Epilog.RELU_AUX_BIAS: {"cublaslt": 11501, "ctk": "11.3.1"},
737
+ Epilog.GELU_BIAS: {"cublaslt": 11501, "ctk": "11.3.1"},
738
+ Epilog.GELU_AUX_BIAS: {"cublaslt": 11501, "ctk": "11.3.1"},
739
+ # 11501, 11.3.1 supports ^
740
+ # 11504, 11.4.1 supports ^
741
+ # 11601, 11.4.2 supports ^
742
+ # 11703, 11.5.0 supports ^
743
+ # 11704, 11.5.1 supports ^
744
+ # 11801, 11.6.0 supports ^
745
+ # 11801, 11.6.1 supports ^
746
+ # 110902, 11.6.2 supports ^
747
+ # Even though BGRAD[A,B] and D[R,G]ELU appear in earlier headers, our unit tests mark
748
+ # them as unsupported before 111103 for in order to avoid API changes.
749
+ Epilog.DRELU: {"cublaslt": 111103, "ctk": "11.8.0"},
750
+ Epilog.DGELU: {"cublaslt": 111103, "ctk": "11.8.0"},
751
+ Epilog.BGRADA: {"cublaslt": 111103, "ctk": "11.8.0"},
752
+ Epilog.BGRADB: {"cublaslt": 111103, "ctk": "11.8.0"},
753
+ Epilog.DRELU_BGRAD: {"cublaslt": 111103, "ctk": "11.8.0"},
754
+ Epilog.DGELU_BGRAD: {"cublaslt": 111103, "ctk": "11.8.0"},
755
+ # 111103, 11.8.0 supports ^
756
+ }
757
+
758
+ BATCHED_EPILOG_MINIMUM_VERSIONS_MAP = EPILOG_MINIMUM_VERSIONS_MAP.copy()
759
+ BATCHED_EPILOG_MINIMUM_VERSIONS_MAP.update(
760
+ {
761
+ Epilog.RELU_AUX: {"cublaslt": 11703, "ctk": "11.5"},
762
+ Epilog.GELU_AUX: {"cublaslt": 11703, "ctk": "11.5"},
763
+ Epilog.RELU_AUX_BIAS: {"cublaslt": 11703, "ctk": "11.5"},
764
+ Epilog.GELU_AUX_BIAS: {"cublaslt": 11703, "ctk": "11.5"},
765
+ }
766
+ )