Skip to content

Commit 43d7a79

Browse files
matajohcdrnet
authored andcommitted
Further cleanup of exceptions, added API specific exception classes and created a shared struct for passing exception information.
1 parent 3f11f41 commit 43d7a79

File tree

10 files changed

+488
-142
lines changed

10 files changed

+488
-142
lines changed

src/NativeProviders/CUDA/blas.cpp

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -93,88 +93,112 @@ void cuda_gemm(const cublasHandle_t handle, const cublasOperation_t transa, cons
9393

9494
extern "C" {
9595

96-
DLLEXPORT void s_axpy(const cublasHandle_t blasHandle, const int n, const float alpha, const float x[], float y[], cudaError_t *error, cublasStatus_t *blasStatus){
97-
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasSaxpy, error, blasStatus);
96+
DLLEXPORT CudaResults s_axpy(const cublasHandle_t blasHandle, const int n, const float alpha, const float x[], float y[]){
97+
CudaResults ret;
98+
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasSaxpy, &ret.error, &ret.blasStatus);
99+
return ret;
98100
}
99101

100-
DLLEXPORT void d_axpy(const cublasHandle_t blasHandle, const int n, const double alpha, const double x[], double y[], cudaError_t *error, cublasStatus_t *blasStatus){
101-
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasDaxpy, error, blasStatus);
102+
DLLEXPORT CudaResults d_axpy(const cublasHandle_t blasHandle, const int n, const double alpha, const double x[], double y[]){
103+
CudaResults ret;
104+
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasDaxpy, &ret.error, &ret.blasStatus);
105+
return ret;
102106
}
103107

104-
DLLEXPORT void c_axpy(const cublasHandle_t blasHandle, const int n, const cuComplex alpha, const cuComplex x[], cuComplex y[], cudaError_t *error, cublasStatus_t *blasStatus){
105-
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasCaxpy, error, blasStatus);
108+
DLLEXPORT CudaResults c_axpy(const cublasHandle_t blasHandle, const int n, const cuComplex alpha, const cuComplex x[], cuComplex y[]){
109+
CudaResults ret;
110+
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasCaxpy, &ret.error, &ret.blasStatus);
111+
return ret;
106112
}
107113

108-
DLLEXPORT void z_axpy(const cublasHandle_t blasHandle, const int n, const cuDoubleComplex alpha, const cuDoubleComplex x[], cuDoubleComplex y[], cudaError_t *error, cublasStatus_t *blasStatus){
109-
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasZaxpy, error, blasStatus);
114+
DLLEXPORT CudaResults z_axpy(const cublasHandle_t blasHandle, const int n, const cuDoubleComplex alpha, const cuDoubleComplex x[], cuDoubleComplex y[]){
115+
CudaResults ret;
116+
cuda_axpy(blasHandle, n, alpha, x, 1, y, 1, cublasZaxpy, &ret.error, &ret.blasStatus);
117+
return ret;
110118
}
111119

112-
DLLEXPORT void s_scale(const cublasHandle_t blasHandle, const int n, const float alpha, float x[], cudaError_t *error, cublasStatus_t *blasStatus){
113-
cuda_scal(blasHandle, n, alpha, x, 1, cublasSscal, error, blasStatus);
120+
DLLEXPORT CudaResults s_scale(const cublasHandle_t blasHandle, const int n, const float alpha, float x[]){
121+
CudaResults ret;
122+
cuda_scal(blasHandle, n, alpha, x, 1, cublasSscal, &ret.error, &ret.blasStatus);
123+
return ret;
114124
}
115125

116-
DLLEXPORT void d_scale(const cublasHandle_t blasHandle, const int n, const double alpha, double x[], cudaError_t *error, cublasStatus_t *blasStatus){
117-
cuda_scal(blasHandle, n, alpha, x, 1, cublasDscal, error, blasStatus);
126+
DLLEXPORT CudaResults d_scale(const cublasHandle_t blasHandle, const int n, const double alpha, double x[]){
127+
CudaResults ret;
128+
cuda_scal(blasHandle, n, alpha, x, 1, cublasDscal, &ret.error, &ret.blasStatus);
129+
return ret;
118130
}
119131

120-
DLLEXPORT void c_scale(const cublasHandle_t blasHandle, const int n, const cuComplex alpha, cuComplex x[], cudaError_t *error, cublasStatus_t *blasStatus){
121-
cuda_scal(blasHandle, n, alpha, x, 1, cublasCscal, error, blasStatus);
132+
DLLEXPORT CudaResults c_scale(const cublasHandle_t blasHandle, const int n, const cuComplex alpha, cuComplex x[]){
133+
CudaResults ret;
134+
cuda_scal(blasHandle, n, alpha, x, 1, cublasCscal, &ret.error, &ret.blasStatus);
135+
return ret;
122136
}
123137

124-
DLLEXPORT void z_scale(const cublasHandle_t blasHandle, const int n, const cuDoubleComplex alpha, cuDoubleComplex x[], cudaError_t *error, cublasStatus_t *blasStatus){
125-
cuda_scal(blasHandle, n, alpha, x, 1, cublasZscal, error, blasStatus);
138+
DLLEXPORT CudaResults z_scale(const cublasHandle_t blasHandle, const int n, const cuDoubleComplex alpha, cuDoubleComplex x[]){
139+
CudaResults ret;
140+
cuda_scal(blasHandle, n, alpha, x, 1, cublasZscal, &ret.error, &ret.blasStatus);
141+
return ret;
126142
}
127143

128-
DLLEXPORT float s_dot_product(const cublasHandle_t blasHandle, const int n, const float x[], const float y[], cudaError_t *error, cublasStatus_t *blasStatus){
129-
float ret;
130-
cuda_dot(blasHandle, n, x, 1, y, 1, &ret, cublasSdot, error, blasStatus);
144+
DLLEXPORT CudaResults s_dot_product(const cublasHandle_t blasHandle, const int n, const float x[], const float y[], float *result){
145+
CudaResults ret;
146+
cuda_dot(blasHandle, n, x, 1, y, 1, result, cublasSdot, &ret.error, &ret.blasStatus);
131147
return ret;
132148
}
133149

134-
DLLEXPORT double d_dot_product(const cublasHandle_t blasHandle, const int n, const double x[], const double y[], cudaError_t *error, cublasStatus_t *blasStatus){
135-
double ret;
136-
cuda_dot(blasHandle, n, x, 1, y, 1, &ret, cublasDdot, error, blasStatus);
150+
DLLEXPORT CudaResults d_dot_product(const cublasHandle_t blasHandle, const int n, const double x[], const double y[], double *result){
151+
CudaResults ret;
152+
cuda_dot(blasHandle, n, x, 1, y, 1, result, cublasDdot, &ret.error, &ret.blasStatus);
137153
return ret;
138154
}
139155

140-
DLLEXPORT cuComplex c_dot_product(const cublasHandle_t blasHandle, const int n, const cuComplex x[], const cuComplex y[], cudaError_t *error, cublasStatus_t *blasStatus){
141-
cuComplex ret;
142-
cuda_dot(blasHandle, n, x, 1, y, 1, &ret, cublasCdotu, error, blasStatus);
156+
DLLEXPORT CudaResults c_dot_product(const cublasHandle_t blasHandle, const int n, const cuComplex x[], const cuComplex y[], cuComplex *result){
157+
CudaResults ret;
158+
cuda_dot(blasHandle, n, x, 1, y, 1, result, cublasCdotu, &ret.error, &ret.blasStatus);
143159
return ret;
144160
}
145161

146-
DLLEXPORT cuDoubleComplex z_dot_product(const cublasHandle_t blasHandle, const int n, const cuDoubleComplex x[], const cuDoubleComplex y[], cudaError_t *error, cublasStatus_t *blasStatus){
147-
cuDoubleComplex ret;
148-
cuda_dot(blasHandle, n, x, 1, y, 1, &ret, cublasZdotu, error, blasStatus);
162+
DLLEXPORT CudaResults z_dot_product(const cublasHandle_t blasHandle, const int n, const cuDoubleComplex x[], const cuDoubleComplex y[], cuDoubleComplex *result){
163+
CudaResults ret;
164+
cuda_dot(blasHandle, n, x, 1, y, 1, result, cublasZdotu, &ret.error, &ret.blasStatus);
149165
return ret;
150166
}
151167

152-
DLLEXPORT void s_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const float alpha, const float x[], const float y[], const float beta, float c[], cudaError_t *error, cublasStatus_t *blasStatus){
168+
DLLEXPORT CudaResults s_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const float alpha, const float x[], const float y[], const float beta, float c[]){
169+
CudaResults ret;
153170
int lda = transA == CUBLAS_OP_N ? m : k;
154171
int ldb = transB == CUBLAS_OP_N ? k : n;
155172

156-
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasSgemm, error, blasStatus);
173+
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasSgemm, &ret.error, &ret.blasStatus);
174+
return ret;
157175
}
158176

159-
DLLEXPORT void d_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const double alpha, const double x[], const double y[], const double beta, double c[], cudaError_t *error, cublasStatus_t *blasStatus){
177+
DLLEXPORT CudaResults d_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const double alpha, const double x[], const double y[], const double beta, double c[]){
178+
CudaResults ret;
160179
int lda = transA == CUBLAS_OP_N ? m : k;
161180
int ldb = transB == CUBLAS_OP_N ? k : n;
162181

163-
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasDgemm, error, blasStatus);
182+
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasDgemm, &ret.error, &ret.blasStatus);
183+
return ret;
164184
}
165185

166-
DLLEXPORT void c_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const cuComplex alpha, const cuComplex x[], const cuComplex y[], const cuComplex beta, cuComplex c[], cudaError_t *error, cublasStatus_t *blasStatus){
186+
DLLEXPORT CudaResults c_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const cuComplex alpha, const cuComplex x[], const cuComplex y[], const cuComplex beta, cuComplex c[]){
187+
CudaResults ret;
167188
int lda = transA == CUBLAS_OP_N ? m : k;
168189
int ldb = transB == CUBLAS_OP_N ? k : n;
169190

170-
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasCgemm, error, blasStatus);
191+
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasCgemm, &ret.error, &ret.blasStatus);
192+
return ret;
171193
}
172194

173-
DLLEXPORT void z_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const cuDoubleComplex alpha, const cuDoubleComplex x[], const cuDoubleComplex y[], const cuDoubleComplex beta, cuDoubleComplex c[], cudaError_t *error, cublasStatus_t *blasStatus){
195+
DLLEXPORT CudaResults z_matrix_multiply(const cublasHandle_t blasHandle, cublasOperation_t transA, cublasOperation_t transB, const int m, const int n, const int k, const cuDoubleComplex alpha, const cuDoubleComplex x[], const cuDoubleComplex y[], const cuDoubleComplex beta, cuDoubleComplex c[]){
196+
CudaResults ret;
174197
int lda = transA == CUBLAS_OP_N ? m : k;
175198
int ldb = transB == CUBLAS_OP_N ? k : n;
176199

177-
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasZgemm, error, blasStatus);
200+
cuda_gemm(blasHandle, transA, transB, m, n, k, alpha, x, lda, y, ldb, beta, c, m, cublasZgemm, &ret.error, &ret.blasStatus);
201+
return ret;
178202
}
179203

180204
}

src/NativeProviders/CUDA/capabilities.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "wrapper_common.h"
2+
#include "cuda_runtime.h"
23
#include "cublas_v2.h"
34
#include "cusolverDn.h"
45

@@ -14,6 +15,24 @@ extern "C" {
1415
*/
1516
DLLEXPORT int query_capability(const int capability)
1617
{
18+
int count;
19+
int device;
20+
cudaDeviceProp prop;
21+
22+
if (cudaGetDeviceCount(&count))
23+
return 0;
24+
25+
if (count == 0)
26+
return 0;
27+
28+
if (cudaGetDevice(&device))
29+
return 0;
30+
31+
if (cudaGetDeviceProperties(&prop, device))
32+
return 0;
33+
34+
35+
1736
switch (capability)
1837
{
1938

@@ -42,10 +61,12 @@ extern "C" {
4261
#endif
4362

4463
// COMMON/SHARED
45-
case 64: return 1; // revision
64+
case 64:
65+
return prop.major;
4666

4767
// LINEAR ALGEBRA
48-
case 128: return 1; // basic dense linear algebra
68+
case 128:
69+
return prop.major >= 2;
4970

5071
// OPTIMIZATION
5172
case 256: return 0; // basic optimization

src/NativeProviders/CUDA/wrapper_cuda.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22
#define WRAPPER_CUDA_H
33

44
#include "wrapper_common.h"
5+
#include "cuda_runtime.h"
6+
#include "cusolver_common.h"
57

68
#define SAFECUDACALL(error,call) {*error = call; if(*error){goto exit;}}
79

10+
typedef struct
11+
{
12+
cudaError_t error;
13+
cublasStatus_t blasStatus;
14+
cusolverStatus_t solverStatus;
15+
} CudaResults;
16+
817
#endif

src/Numerics/Numerics.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,16 @@
159159
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Double.cs" />
160160
<Compile Include="Providers\LinearAlgebra\Acml\AcmlLinearAlgebraProvider.Single.cs" />
161161
<Compile Include="Providers\LinearAlgebra\Acml\SafeNativeMethods.cs" />
162+
<Compile Include="Providers\LinearAlgebra\Cuda\CuBLASException.cs" />
163+
<Compile Include="Providers\LinearAlgebra\Cuda\CudaException.cs" />
162164
<Compile Include="Providers\LinearAlgebra\Cuda\CudaLinearAlgebraProvider.Complex.cs" />
163165
<Compile Include="Providers\LinearAlgebra\Cuda\CudaLinearAlgebraProvider.Complex32.cs" />
164166
<Compile Include="Providers\LinearAlgebra\Cuda\CudaLinearAlgebraProvider.cs" />
165167
<Compile Include="Providers\LinearAlgebra\Cuda\CudaLinearAlgebraProvider.Double.cs" />
166168
<Compile Include="Providers\LinearAlgebra\Cuda\CudaLinearAlgebraProvider.Single.cs" />
167169
<Compile Include="Providers\LinearAlgebra\Cuda\CudaProviderCapabilities.cs" />
170+
<Compile Include="Providers\LinearAlgebra\Cuda\CudaResults.cs" />
171+
<Compile Include="Providers\LinearAlgebra\Cuda\CuSolverException.cs" />
168172
<Compile Include="Providers\LinearAlgebra\Cuda\SafeNativeMethods.cs" />
169173
<Compile Include="Providers\LinearAlgebra\Mkl\MklProviderCapabilities.cs" />
170174
<Compile Include="Providers\LinearAlgebra\OpenBlas\OpenBlasLinearAlgebraProvider.cs" />
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// <copyright file="CuSolverException.cs" company="Math.NET">
2+
// Math.NET Numerics, part of the Math.NET Project
3+
// http://numerics.mathdotnet.com
4+
// http://github.com/mathnet/mathnet-numerics
5+
// http://mathnetnumerics.codeplex.com
6+
//
7+
// Copyright (c) 2009-2013 Math.NET
8+
//
9+
// Permission is hereby granted, free of charge, to any person
10+
// obtaining a copy of this software and associated documentation
11+
// files (the "Software"), to deal in the Software without
12+
// restriction, including without limitation the rights to use,
13+
// copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
// copies of the Software, and to permit persons to whom the
15+
// Software is furnished to do so, subject to the following
16+
// conditions:
17+
//
18+
// The above copyright notice and this permission notice shall be
19+
// included in all copies or substantial portions of the Software.
20+
//
21+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28+
// OTHER DEALINGS IN THE SOFTWARE.
29+
// </copyright>
30+
31+
using System;
32+
using System.Collections.Generic;
33+
using System.Linq;
34+
using System.Text;
35+
36+
namespace MathNet.Numerics.Providers.LinearAlgebra.Cuda
37+
{
38+
/// <summary>
39+
/// Exceptions thrown by the cuSolverDn API.
40+
/// </summary>
41+
public class CuSolverException : Exception
42+
{
43+
/// <summary>
44+
/// Initializes a new instance of the <see cref="CuSolverException"/> class.
45+
/// </summary>
46+
/// <param name="statusCode">The status code returned from the API</param>
47+
public CuSolverException(int statusCode)
48+
: base(CuSolverException.GetErrorMessage(statusCode))
49+
{
50+
this.StatusCode = statusCode;
51+
}
52+
53+
/// <summary>
54+
/// Gets the status code returned by the cuSolverDn API
55+
/// </summary>
56+
public int StatusCode { get; private set; }
57+
58+
/// <summary>
59+
/// Returns the appropriate error message for each status code.
60+
/// </summary>
61+
/// <param name="code">The status code returned from the API</param>
62+
/// <returns>The corresponding error message</returns>
63+
private static string GetErrorMessage(int statusCode)
64+
{
65+
switch (statusCode)
66+
{
67+
case 0: // CUSOLVER_STATUS_SUCCESS
68+
return "The operation completed successfully.";
69+
70+
case 1: // CUSOLVER_STATUS_NOT_INITIALIZED
71+
return "The cuSolver library was not initialized. This is usually caused by the lack of a prior call, an error in the CUDA Runtime API called by the cuSolver routine, or an error in the hardware setup.";
72+
73+
case 2: // CUSOLVER_STATUS_ALLOC_FAILED
74+
return "Resource allocation failed inside the cuSolver library. This is usually caused by a cudaMalloc() failure.";
75+
76+
case 3: // CUSOLVER_STATUS_INVALID_VALUE
77+
return "An unsupported value or parameter was passed to the function (a negative vector size, for example).";
78+
79+
case 4: // CUSOLVER_STATUS_ARCH_MISMATCH
80+
return "The function requires a feature absent from the device architecture; usually caused by the lack of support for atomic operations or double precision.";
81+
82+
case 5: // CUSOLVER_STATUS_MAPPING_ERROR
83+
return "Mapping Error";
84+
85+
case 6: // CUSOLVER_STATUS_EXECUTION_FAILED
86+
return "The GPU program failed to execute. This is often caused by a launch failure of the kernel on the GPU, which can be caused by multiple reasons.";
87+
88+
case 7: //CUSOLVER_STATUS_INTERNAL_ERROR
89+
return "An internal cuSolver operation failed. This error is usually caused by a cudaMemcpyAsync() failure.";
90+
91+
case 8: // CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED
92+
return "The matrix type is not supported by this function. This is usually caused by passing an invalid matrix descriptor to the function.";
93+
94+
case 9: // CUSOLVER_STATUS_NOT_SUPPORTED
95+
return "The functionality requested is not supported";
96+
97+
case 10: // CUSOLVER_STATUS_ZERO_PIVOT
98+
return "Zero Pivot";
99+
100+
case 11: //CUSOLVER_STATUS_INVALID_LICENSE
101+
return "The functionality requested requires some license and an error was detected when trying to check the current licensing. This error can happen if the license is not present or is expired or if the environment variable NVIDIA_LICENSE_FILE is not set properly.";
102+
103+
default:
104+
throw new Exception("Unrecognized cuSolverDn status code");
105+
106+
107+
}
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)