summaryrefslogtreecommitdiff
path: root/src/routines/level3/xhemm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/routines/level3/xhemm.cpp')
-rw-r--r--src/routines/level3/xhemm.cpp132
1 files changed, 63 insertions, 69 deletions
diff --git a/src/routines/level3/xhemm.cpp b/src/routines/level3/xhemm.cpp
index 9813503e..e5b1502a 100644
--- a/src/routines/level3/xhemm.cpp
+++ b/src/routines/level3/xhemm.cpp
@@ -29,7 +29,7 @@ Xhemm<T>::Xhemm(Queue &queue, EventPointer event, const std::string &name):
// The main routine
template <typename T>
-StatusCode Xhemm<T>::DoHemm(const Layout layout, const Side side, const Triangle triangle,
+void Xhemm<T>::DoHemm(const Layout layout, const Side side, const Triangle triangle,
const size_t m, const size_t n,
const T alpha,
const Buffer<T> &a_buffer, const size_t a_offset, const size_t a_ld,
@@ -38,15 +38,14 @@ StatusCode Xhemm<T>::DoHemm(const Layout layout, const Side side, const Triangle
const Buffer<T> &c_buffer, const size_t c_offset, const size_t c_ld) {
// Makes sure all dimensions are larger than zero
- if ((m == 0) || (n == 0) ) { return StatusCode::kInvalidDimension; }
+ if ((m == 0) || (n == 0) ) { throw BLASError(StatusCode::kInvalidDimension); }
// Computes the k dimension. This is based on whether or not the hermitian matrix is A (on the
// left) or B (on the right) in the Xgemm routine.
auto k = (side == Side::kLeft) ? m : n;
// Checks for validity of the squared A matrix
- auto status = TestMatrixA(k, k, a_buffer, a_offset, a_ld);
- if (ErrorIn(status)) { return status; }
+ TestMatrixA(k, k, a_buffer, a_offset, a_ld);
// Determines which kernel to run based on the layout (the Xgemm kernel assumes column-major as
// default) and on whether we are dealing with an upper or lower triangle of the hermitian matrix
@@ -55,73 +54,68 @@ StatusCode Xhemm<T>::DoHemm(const Layout layout, const Side side, const Triangle
auto kernel_name = (is_upper) ? "HermUpperToSquared" : "HermLowerToSquared";
// Temporary buffer for a copy of the hermitian matrix
- try {
- auto temp_herm = Buffer<T>(context_, k*k);
-
- // Creates a general matrix from the hermitian matrix to be able to run the regular Xgemm
- // routine afterwards
+ auto temp_herm = Buffer<T>(context_, k*k);
+
+ // Creates a general matrix from the hermitian matrix to be able to run the regular Xgemm
+ // routine afterwards
+ const auto program = GetProgramFromCache(context_, PrecisionValue<T>(), routine_name_);
+ auto kernel = Kernel(program, kernel_name);
+
+ // Sets the arguments for the hermitian-to-squared kernel
+ kernel.SetArgument(0, static_cast<int>(k));
+ kernel.SetArgument(1, static_cast<int>(a_ld));
+ kernel.SetArgument(2, static_cast<int>(a_offset));
+ kernel.SetArgument(3, a_buffer());
+ kernel.SetArgument(4, static_cast<int>(k));
+ kernel.SetArgument(5, static_cast<int>(k));
+ kernel.SetArgument(6, static_cast<int>(0));
+ kernel.SetArgument(7, temp_herm());
+
+ // Uses the common padding kernel's thread configuration. This is allowed, since the
+ // hermitian-to-squared kernel uses the same parameters.
+ auto global = std::vector<size_t>{Ceil(CeilDiv(k, db_["PAD_WPTX"]), db_["PAD_DIMX"]),
+ Ceil(CeilDiv(k, db_["PAD_WPTY"]), db_["PAD_DIMY"])};
+ auto local = std::vector<size_t>{db_["PAD_DIMX"], db_["PAD_DIMY"]};
+ auto kernelEvent = Event();
+ RunKernel(kernel, queue_, device_, global, local, kernelEvent.pointer());
+
+ // Synchronize now: 'DoGemm' does not accept a list of events to wait for
+ kernelEvent.WaitForCompletion();
+
+ // Runs the regular Xgemm code with either "C := AB+C" or ...
+ if (side == Side::kLeft) {
+ DoGemm(layout, Transpose::kNo, Transpose::kNo,
+ m, n, k,
+ alpha,
+ temp_herm, 0, k,
+ b_buffer, b_offset, b_ld,
+ beta,
+ c_buffer, c_offset, c_ld);
+ }
+
+ // ... with "C := BA+C". Note that A and B are now reversed.
+ else {
try {
- const auto program = GetProgramFromCache(context_, PrecisionValue<T>(), routine_name_);
- auto kernel = Kernel(program, kernel_name);
-
- // Sets the arguments for the hermitian-to-squared kernel
- kernel.SetArgument(0, static_cast<int>(k));
- kernel.SetArgument(1, static_cast<int>(a_ld));
- kernel.SetArgument(2, static_cast<int>(a_offset));
- kernel.SetArgument(3, a_buffer());
- kernel.SetArgument(4, static_cast<int>(k));
- kernel.SetArgument(5, static_cast<int>(k));
- kernel.SetArgument(6, static_cast<int>(0));
- kernel.SetArgument(7, temp_herm());
-
- // Uses the common padding kernel's thread configuration. This is allowed, since the
- // hermitian-to-squared kernel uses the same parameters.
- auto global = std::vector<size_t>{Ceil(CeilDiv(k, db_["PAD_WPTX"]), db_["PAD_DIMX"]),
- Ceil(CeilDiv(k, db_["PAD_WPTY"]), db_["PAD_DIMY"])};
- auto local = std::vector<size_t>{db_["PAD_DIMX"], db_["PAD_DIMY"]};
- auto kernelEvent = Event();
- status = RunKernel(kernel, queue_, device_, global, local, kernelEvent.pointer());
- if (ErrorIn(status)) { return status; }
-
- // Synchronize now: 'DoGemm' does not accept a list of events to wait for
- kernelEvent.WaitForCompletion();
-
- // Runs the regular Xgemm code with either "C := AB+C" or ...
- if (side == Side::kLeft) {
- status = DoGemm(layout, Transpose::kNo, Transpose::kNo,
- m, n, k,
- alpha,
- temp_herm, 0, k,
- b_buffer, b_offset, b_ld,
- beta,
- c_buffer, c_offset, c_ld);
- }
-
- // ... with "C := BA+C". Note that A and B are now reversed.
- else {
- status = DoGemm(layout, Transpose::kNo, Transpose::kNo,
- m, n, k,
- alpha,
- b_buffer, b_offset, b_ld,
- temp_herm, 0, k,
- beta,
- c_buffer, c_offset, c_ld);
-
- // A and B are now reversed, so also reverse the error codes returned from the Xgemm routine
- switch(status) {
- case StatusCode::kInvalidMatrixA: status = StatusCode::kInvalidMatrixB; break;
- case StatusCode::kInvalidMatrixB: status = StatusCode::kInvalidMatrixA; break;
- case StatusCode::kInvalidLeadDimA: status = StatusCode::kInvalidLeadDimB; break;
- case StatusCode::kInvalidLeadDimB: status = StatusCode::kInvalidLeadDimA; break;
- case StatusCode::kInsufficientMemoryA: status = StatusCode::kInsufficientMemoryB; break;
- case StatusCode::kInsufficientMemoryB: status = StatusCode::kInsufficientMemoryA; break;
- }
+ DoGemm(layout, Transpose::kNo, Transpose::kNo,
+ m, n, k,
+ alpha,
+ b_buffer, b_offset, b_ld,
+ temp_herm, 0, k,
+ beta,
+ c_buffer, c_offset, c_ld);
+ } catch (BLASError &e) {
+ // A and B are now reversed, so also reverse the error codes returned from the Xgemm routine
+ switch(e.status()) {
+ case StatusCode::kInvalidMatrixA: throw BLASError(StatusCode::kInvalidMatrixB, e.details());
+ case StatusCode::kInvalidMatrixB: throw BLASError(StatusCode::kInvalidMatrixA, e.details());
+ case StatusCode::kInvalidLeadDimA: throw BLASError(StatusCode::kInvalidLeadDimB, e.details());
+ case StatusCode::kInvalidLeadDimB: throw BLASError(StatusCode::kInvalidLeadDimA, e.details());
+ case StatusCode::kInsufficientMemoryA: throw BLASError(StatusCode::kInsufficientMemoryB, e.details());
+ case StatusCode::kInsufficientMemoryB: throw BLASError(StatusCode::kInsufficientMemoryA, e.details());
+ default: throw;
}
-
- // Return the status of the Xgemm routine
- return status;
- } catch (...) { return StatusCode::kInvalidKernel; }
- } catch (...) { return StatusCode::kTempBufferAllocFailure; }
+ }
+ }
}
// =================================================================================================