summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCedric Nugteren <web@cedricnugteren.nl>2015-07-15 22:27:56 +0200
committerCedric Nugteren <web@cedricnugteren.nl>2015-07-15 22:27:56 +0200
commit3bb1b5fa6e26ca95065ac68a48f4b0a51870fe88 (patch)
tree2e4b8249122aecd29f2706bad2cc06340d891965 /src
parent530418f06f6f5523767b4b2529c45ad45e99b2a2 (diff)
parent6908c4ebd2784a4a0187b3752d2427f46445b7bf (diff)
Merge pull request #13 from CNugteren/bypass_pre_post_processing
Bypass pre/post-processing
Diffstat (limited to 'src')
-rw-r--r--src/routine.cc14
-rw-r--r--src/routines/level3/xgemm.cc73
-rw-r--r--src/routines/level3/xher2k.cc84
-rw-r--r--src/routines/level3/xherk.cc56
-rw-r--r--src/routines/level3/xsyr2k.cc57
-rw-r--r--src/routines/level3/xsyrk.cc41
6 files changed, 200 insertions, 125 deletions
diff --git a/src/routine.cc b/src/routine.cc
index d11edb0f..339027d4 100644
--- a/src/routine.cc
+++ b/src/routine.cc
@@ -202,17 +202,17 @@ StatusCode Routine::TestVectorY(const size_t n, const Buffer &buffer, const size
// =================================================================================================
-// Copies a matrix and pads it with zeros
+// Copies or transposes a matrix and pads/unpads it with zeros
StatusCode Routine::PadCopyTransposeMatrix(const size_t src_one, const size_t src_two,
const size_t src_ld, const size_t src_offset,
const Buffer &src,
const size_t dest_one, const size_t dest_two,
const size_t dest_ld, const size_t dest_offset,
const Buffer &dest,
+ const Program &program, const bool do_pad,
const bool do_transpose, const bool do_conjugate,
- const bool pad, const bool upper, const bool lower,
- const bool diagonal_imag_zero,
- const Program &program) {
+ const bool upper, const bool lower,
+ const bool diagonal_imag_zero) {
// Determines whether or not the fast-version could potentially be used
auto use_fast_kernel = (src_offset == 0) && (dest_offset == 0) && (do_conjugate == false) &&
@@ -230,7 +230,7 @@ StatusCode Routine::PadCopyTransposeMatrix(const size_t src_one, const size_t sr
}
else {
use_fast_kernel = false;
- kernel_name = (pad) ? "PadTransposeMatrix" : "UnPadTransposeMatrix";
+ kernel_name = (do_pad) ? "PadTransposeMatrix" : "UnPadTransposeMatrix";
}
}
else {
@@ -242,7 +242,7 @@ StatusCode Routine::PadCopyTransposeMatrix(const size_t src_one, const size_t sr
}
else {
use_fast_kernel = false;
- kernel_name = (pad) ? "PadMatrix" : "UnPadMatrix";
+ kernel_name = (do_pad) ? "PadMatrix" : "UnPadMatrix";
}
}
@@ -267,7 +267,7 @@ StatusCode Routine::PadCopyTransposeMatrix(const size_t src_one, const size_t sr
kernel.SetArgument(7, static_cast<int>(dest_ld));
kernel.SetArgument(8, static_cast<int>(dest_offset));
kernel.SetArgument(9, dest());
- if (pad) {
+ if (do_pad) {
kernel.SetArgument(10, static_cast<int>(do_conjugate));
}
else {
diff --git a/src/routines/level3/xgemm.cc b/src/routines/level3/xgemm.cc
index f4a9f737..950a8550 100644
--- a/src/routines/level3/xgemm.cc
+++ b/src/routines/level3/xgemm.cc
@@ -95,31 +95,48 @@ StatusCode Xgemm<T>::DoGemm(const Layout layout,
auto n_ceiled = Ceil(n, db_["NWG"]);
auto k_ceiled = Ceil(k, db_["KWG"]);
- // Allocates space on the device for padded and/or transposed input and output matrices.
+ // The padded/transposed input/output matrices: if memory allocation fails, throw an exception
try {
- auto temp_a = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*m_ceiled*sizeof(T));
- auto temp_b = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_c = Buffer(context_, CL_MEM_READ_WRITE, m_ceiled*n_ceiled*sizeof(T));
// Loads the program from the database
auto& program = GetProgramFromCache();
- // Runs the pre-processing kernels. This transposes the matrices, but also pads zeros to fill
- // them up until they reach a certain multiple of size (kernel parameter dependent).
- status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
- m_ceiled, k_ceiled, m_ceiled, 0, temp_a,
- a_do_transpose, a_conjugate, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
- status = PadCopyTransposeMatrix(b_one, b_two, b_ld, b_offset, b_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_b,
- b_do_transpose, b_conjugate, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
-
- // Only necessary for matrix C if it used both as input and output
- if (beta != static_cast<T>(0)) {
+ // Determines whether or not temporary matrices are needed
+ auto a_no_temp = a_one == m_ceiled && a_two == k_ceiled && a_ld == m_ceiled && a_offset == 0 &&
+ a_do_transpose == false && a_conjugate == false;
+ auto b_no_temp = b_one == n_ceiled && b_two == k_ceiled && b_ld == n_ceiled && b_offset == 0 &&
+ b_do_transpose == false && b_conjugate == false;
+ auto c_no_temp = c_one == m_ceiled && c_two == n_ceiled && c_ld == m_ceiled && c_offset == 0 &&
+ c_do_transpose == false;
+
+ // Creates the temporary matrices
+ auto a_temp = (a_no_temp) ? a_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*m_ceiled*sizeof(T));
+ auto b_temp = (b_no_temp) ? b_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto c_temp = (c_no_temp) ? c_buffer : Buffer(context_, CL_MEM_READ_WRITE, m_ceiled*n_ceiled*sizeof(T));
+
+ // Runs the pre-processing kernel for matrix A. This transposes the matrix, but also pads zeros
+ // to fill it up until it reaches a certain multiple of size (kernel parameter dependent). In
+ // case nothing has to be done, these kernels can be skipped.
+ if (!a_no_temp) {
+ status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
+ m_ceiled, k_ceiled, m_ceiled, 0, a_temp,
+ program, true, a_do_transpose, a_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
+
+ // As above, but now for matrix B
+ if (!b_no_temp) {
+ status = PadCopyTransposeMatrix(b_one, b_two, b_ld, b_offset, b_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, b_temp,
+ program, true, b_do_transpose, b_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
+
+ // As above, but now for matrix C. This is only necessary if C is used both as input and output.
+ if (!c_no_temp && beta != static_cast<T>(0)) {
status = PadCopyTransposeMatrix(c_one, c_two, c_ld, c_offset, c_buffer,
- m_ceiled, n_ceiled, m_ceiled, 0, temp_c,
- c_do_transpose, false, true, false, false, false, program);
+ m_ceiled, n_ceiled, m_ceiled, 0, c_temp,
+ program, true, c_do_transpose, false);
if (ErrorIn(status)) { return status; }
}
@@ -133,9 +150,9 @@ StatusCode Xgemm<T>::DoGemm(const Layout layout,
kernel.SetArgument(2, static_cast<int>(k_ceiled));
kernel.SetArgument(3, alpha);
kernel.SetArgument(4, beta);
- kernel.SetArgument(5, temp_a());
- kernel.SetArgument(6, temp_b());
- kernel.SetArgument(7, temp_c());
+ kernel.SetArgument(5, a_temp());
+ kernel.SetArgument(6, b_temp());
+ kernel.SetArgument(7, c_temp());
// Computes the global and local thread sizes
auto global = std::vector<size_t>{
@@ -148,11 +165,13 @@ StatusCode Xgemm<T>::DoGemm(const Layout layout,
status = RunKernel(kernel, global, local);
if (ErrorIn(status)) { return status; }
- // Runs the post-processing kernel
- status = PadCopyTransposeMatrix(m_ceiled, n_ceiled, m_ceiled, 0, temp_c,
- c_one, c_two, c_ld, c_offset, c_buffer,
- c_do_transpose, false, false, false, false, false, program);
- if (ErrorIn(status)) { return status; }
+ // Runs the post-processing kernel if needed
+ if (!c_no_temp) {
+ status = PadCopyTransposeMatrix(m_ceiled, n_ceiled, m_ceiled, 0, c_temp,
+ c_one, c_two, c_ld, c_offset, c_buffer,
+ program, false, c_do_transpose, false);
+ if (ErrorIn(status)) { return status; }
+ }
// Successfully finished the computation
return StatusCode::kSuccess;
diff --git a/src/routines/level3/xher2k.cc b/src/routines/level3/xher2k.cc
index 6d33a0e1..45793ca7 100644
--- a/src/routines/level3/xher2k.cc
+++ b/src/routines/level3/xher2k.cc
@@ -81,40 +81,62 @@ StatusCode Xher2k<T,U>::DoHer2k(const Layout layout, const Triangle triangle, co
// Decides which kernel to run: the upper-triangular or lower-triangular version
auto kernel_name = (triangle == Triangle::kUpper) ? "XgemmUpper" : "XgemmLower";
- // Allocates space on the device for padded and/or transposed input and output matrices.
+ // The padded/transposed input/output matrices: if memory allocation fails, throw an exception
try {
- auto temp_a1 = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_b1 = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_a2 = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_b2 = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_c = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
// Loads the program from the database
auto& program = GetProgramFromCache();
+ // Determines whether or not temporary matrices are needed
+ auto a1_no_temp = ab_one == n_ceiled && ab_two == k_ceiled && a_ld == n_ceiled && a_offset == 0 &&
+ ab_rotated == false && ab_conjugate == false;
+ auto a2_no_temp = ab_one == n_ceiled && ab_two == k_ceiled && a_ld == n_ceiled && a_offset == 0 &&
+ ab_rotated == false && ab_conjugate == true;
+ auto b1_no_temp = ab_one == n_ceiled && ab_two == k_ceiled && b_ld == n_ceiled && b_offset == 0 &&
+ ab_rotated == false && ab_conjugate == false;
+ auto b2_no_temp = ab_one == n_ceiled && ab_two == k_ceiled && b_ld == n_ceiled && b_offset == 0 &&
+ ab_rotated == false && ab_conjugate == true;
+
+ // Creates the temporary matrices
+ auto a1_temp = (a1_no_temp) ? a_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto a2_temp = (a2_no_temp) ? a_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto b1_temp = (b1_no_temp) ? b_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto b2_temp = (b2_no_temp) ? b_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto c_temp = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
+
// Runs the pre-processing kernels. This transposes the matrices A and B, but also pads zeros to
- // fill them up until they reach a certain multiple of size (kernel parameter dependent).
- status = PadCopyTransposeMatrix(ab_one, ab_two, a_ld, a_offset, a_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_a1,
- ab_rotated, ab_conjugate, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
- status = PadCopyTransposeMatrix(ab_one, ab_two, a_ld, a_offset, a_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_a2,
- ab_rotated, !ab_conjugate, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
- status = PadCopyTransposeMatrix(ab_one, ab_two, b_ld, b_offset, b_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_b1,
- ab_rotated, ab_conjugate, true, false, false, false, program);
- status = PadCopyTransposeMatrix(ab_one, ab_two, b_ld, b_offset, b_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_b2,
- ab_rotated, !ab_conjugate, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
+ // to fill it up until it reaches a certain multiple of size (kernel parameter dependent). In
+ // case nothing has to be done, these kernels can be skipped.
+ if (!a1_no_temp) {
+ status = PadCopyTransposeMatrix(ab_one, ab_two, a_ld, a_offset, a_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, a1_temp,
+ program, true, ab_rotated, ab_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
+ if (!a2_no_temp) {
+ status = PadCopyTransposeMatrix(ab_one, ab_two, a_ld, a_offset, a_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, a2_temp,
+ program, true, ab_rotated, !ab_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
+ if (!b1_no_temp) {
+ status = PadCopyTransposeMatrix(ab_one, ab_two, b_ld, b_offset, b_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, b1_temp,
+ program, true, ab_rotated, ab_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
+ if (!b2_no_temp) {
+ status = PadCopyTransposeMatrix(ab_one, ab_two, b_ld, b_offset, b_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, b2_temp,
+ program, true, ab_rotated, !ab_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
// Furthermore, also creates a (possibly padded) copy of matrix C, since it is not allowed to
// modify the other triangle.
status = PadCopyTransposeMatrix(n, n, c_ld, c_offset, c_buffer,
- n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
- c_rotated, false, true, false, false, false, program);
+ n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
+ program, true, c_rotated, false);
if (ErrorIn(status)) { return status; }
// Retrieves the XgemmUpper or XgemmLower kernel from the compiled binary
@@ -127,9 +149,9 @@ StatusCode Xher2k<T,U>::DoHer2k(const Layout layout, const Triangle triangle, co
kernel.SetArgument(1, static_cast<int>(k_ceiled));
kernel.SetArgument(2, alpha);
kernel.SetArgument(3, complex_beta);
- kernel.SetArgument(4, temp_a1());
- kernel.SetArgument(5, temp_b2());
- kernel.SetArgument(6, temp_c());
+ kernel.SetArgument(4, a1_temp());
+ kernel.SetArgument(5, b2_temp());
+ kernel.SetArgument(6, c_temp());
// Computes the global and local thread sizes
auto global = std::vector<size_t>{
@@ -147,8 +169,8 @@ StatusCode Xher2k<T,U>::DoHer2k(const Layout layout, const Triangle triangle, co
auto complex_one = T{static_cast<U>(1.0), static_cast<U>(0.0)};
kernel.SetArgument(2, conjugate_alpha);
kernel.SetArgument(3, complex_one);
- kernel.SetArgument(4, temp_b1());
- kernel.SetArgument(5, temp_a2());
+ kernel.SetArgument(4, b1_temp());
+ kernel.SetArgument(5, a2_temp());
// Runs the kernel again
status = RunKernel(kernel, global, local);
@@ -157,9 +179,9 @@ StatusCode Xher2k<T,U>::DoHer2k(const Layout layout, const Triangle triangle, co
// Runs the post-processing kernel
auto upper = (triangle == Triangle::kUpper);
auto lower = (triangle == Triangle::kLower);
- status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
+ status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
n, n, c_ld, c_offset, c_buffer,
- c_rotated, false, false, upper, lower, true, program);
+ program, false, c_rotated, false, upper, lower, true);
if (ErrorIn(status)) { return status; }
// Successfully finished the computation
diff --git a/src/routines/level3/xherk.cc b/src/routines/level3/xherk.cc
index 8fae294f..eaa8861b 100644
--- a/src/routines/level3/xherk.cc
+++ b/src/routines/level3/xherk.cc
@@ -78,32 +78,44 @@ StatusCode Xherk<T,U>::DoHerk(const Layout layout, const Triangle triangle, cons
// Decides which kernel to run: the upper-triangular or lower-triangular version
auto kernel_name = (triangle == Triangle::kUpper) ? "XgemmUpper" : "XgemmLower";
- // Allocates space on the device for padded and/or transposed input and output matrices.
+ // The padded/transposed input/output matrices: if memory allocation fails, throw an exception
try {
- auto temp_a = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_b = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_c = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
// Loads the program from the database
auto& program = GetProgramFromCache();
- // Runs the pre-processing kernel. This transposes the matrix A, but also pads zeros to
- // fill it up until it reaches a certain multiple of size (kernel parameter dependent). It
- // creates two copies:
- status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_a,
- a_rotated, a_conjugate, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
- status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_b,
- a_rotated, b_conjugate, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
+ // Determines whether or not temporary matrices are needed
+ auto a_no_temp = a_one == n_ceiled && a_two == k_ceiled && a_ld == n_ceiled && a_offset == 0 &&
+ a_rotated == false && a_conjugate == false;
+ auto b_no_temp = a_one == n_ceiled && a_two == k_ceiled && a_ld == n_ceiled && a_offset == 0 &&
+ a_rotated == false && b_conjugate == false;
+
+ // Creates the temporary matrices
+ auto a_temp = (a_no_temp) ? a_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto b_temp = (b_no_temp) ? a_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto c_temp = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
+
+ // Runs the pre-processing kernel for matrix A. This transposes the matrix, but also pads zeros
+ // to fill it up until it reaches a certain multiple of size (kernel parameter dependent). In
+ // case nothing has to be done, these kernels can be skipped. Two copies are created.
+ if (!a_no_temp) {
+ status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, a_temp,
+ program, true, a_rotated, a_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
+ if (!b_no_temp) {
+ status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, b_temp,
+ program, true, a_rotated, b_conjugate);
+ if (ErrorIn(status)) { return status; }
+ }
// Furthermore, also creates a (possibly padded) copy of matrix C, since it is not allowed to
// modify the other triangle.
status = PadCopyTransposeMatrix(n, n, c_ld, c_offset, c_buffer,
- n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
- c_rotated, false, true, false, false, false, program);
+ n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
+ program, true, c_rotated, false);
if (ErrorIn(status)) { return status; }
// Retrieves the XgemmUpper or XgemmLower kernel from the compiled binary
@@ -117,9 +129,9 @@ StatusCode Xherk<T,U>::DoHerk(const Layout layout, const Triangle triangle, cons
kernel.SetArgument(1, static_cast<int>(k_ceiled));
kernel.SetArgument(2, complex_alpha);
kernel.SetArgument(3, complex_beta);
- kernel.SetArgument(4, temp_a());
- kernel.SetArgument(5, temp_b());
- kernel.SetArgument(6, temp_c());
+ kernel.SetArgument(4, a_temp());
+ kernel.SetArgument(5, b_temp());
+ kernel.SetArgument(6, c_temp());
// Computes the global and local thread sizes
auto global = std::vector<size_t>{
@@ -135,9 +147,9 @@ StatusCode Xherk<T,U>::DoHerk(const Layout layout, const Triangle triangle, cons
// Runs the post-processing kernel
auto upper = (triangle == Triangle::kUpper);
auto lower = (triangle == Triangle::kLower);
- status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
+ status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
n, n, c_ld, c_offset, c_buffer,
- c_rotated, false, false, upper, lower, true, program);
+ program, false, c_rotated, false, upper, lower, true);
if (ErrorIn(status)) { return status; }
// Successfully finished the computation
diff --git a/src/routines/level3/xsyr2k.cc b/src/routines/level3/xsyr2k.cc
index d54f2fc1..66370827 100644
--- a/src/routines/level3/xsyr2k.cc
+++ b/src/routines/level3/xsyr2k.cc
@@ -79,31 +79,44 @@ StatusCode Xsyr2k<T>::DoSyr2k(const Layout layout, const Triangle triangle, cons
// Decides which kernel to run: the upper-triangular or lower-triangular version
auto kernel_name = (triangle == Triangle::kUpper) ? "XgemmUpper" : "XgemmLower";
- // Allocates space on the device for padded and/or transposed input and output matrices.
+ // The padded/transposed input/output matrices: if memory allocation fails, throw an exception
try {
- auto temp_a = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_b = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_c = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
// Loads the program from the database
auto& program = GetProgramFromCache();
+ // Determines whether or not temporary matrices are needed
+ auto a_no_temp = ab_one == n_ceiled && ab_two == k_ceiled && a_ld == n_ceiled && a_offset == 0 &&
+ ab_rotated == false;
+ auto b_no_temp = ab_one == n_ceiled && ab_two == k_ceiled && b_ld == n_ceiled && b_offset == 0 &&
+ ab_rotated == false;
+
+ // Creates the temporary matrices
+ auto a_temp = (a_no_temp) ? a_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto b_temp = (b_no_temp) ? b_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto c_temp = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
+
// Runs the pre-processing kernels. This transposes the matrices A and B, but also pads zeros to
- // fill them up until they reach a certain multiple of size (kernel parameter dependent).
- status = PadCopyTransposeMatrix(ab_one, ab_two, a_ld, a_offset, a_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_a,
- ab_rotated, false, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
- status = PadCopyTransposeMatrix(ab_one, ab_two, b_ld, b_offset, b_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_b,
- ab_rotated, false, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
+ // to fill it up until it reaches a certain multiple of size (kernel parameter dependent). In
+ // case nothing has to be done, these kernels can be skipped.
+ if (!a_no_temp) {
+ status = PadCopyTransposeMatrix(ab_one, ab_two, a_ld, a_offset, a_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, a_temp,
+ program, true, ab_rotated, false);
+ if (ErrorIn(status)) { return status; }
+ }
+ if (!b_no_temp) {
+ status = PadCopyTransposeMatrix(ab_one, ab_two, b_ld, b_offset, b_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, b_temp,
+ program, true, ab_rotated, false);
+ if (ErrorIn(status)) { return status; }
+ }
// Furthermore, also creates a (possibly padded) copy of matrix C, since it is not allowed to
// modify the other triangle.
status = PadCopyTransposeMatrix(n, n, c_ld, c_offset, c_buffer,
- n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
- c_rotated, false, true, false, false, false, program);
+ n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
+ program, true, c_rotated, false);
if (ErrorIn(status)) { return status; }
// Retrieves the XgemmUpper or XgemmLower kernel from the compiled binary
@@ -115,9 +128,9 @@ StatusCode Xsyr2k<T>::DoSyr2k(const Layout layout, const Triangle triangle, cons
kernel.SetArgument(1, static_cast<int>(k_ceiled));
kernel.SetArgument(2, alpha);
kernel.SetArgument(3, beta);
- kernel.SetArgument(4, temp_a());
- kernel.SetArgument(5, temp_b());
- kernel.SetArgument(6, temp_c());
+ kernel.SetArgument(4, a_temp());
+ kernel.SetArgument(5, b_temp());
+ kernel.SetArgument(6, c_temp());
// Computes the global and local thread sizes
auto global = std::vector<size_t>{
@@ -133,8 +146,8 @@ StatusCode Xsyr2k<T>::DoSyr2k(const Layout layout, const Triangle triangle, cons
// Swaps the arguments for matrices A and B, and sets 'beta' to 1
auto one = static_cast<T>(1);
kernel.SetArgument(3, one);
- kernel.SetArgument(4, temp_b());
- kernel.SetArgument(5, temp_a());
+ kernel.SetArgument(4, b_temp());
+ kernel.SetArgument(5, a_temp());
// Runs the kernel again
status = RunKernel(kernel, global, local);
@@ -143,9 +156,9 @@ StatusCode Xsyr2k<T>::DoSyr2k(const Layout layout, const Triangle triangle, cons
// Runs the post-processing kernel
auto upper = (triangle == Triangle::kUpper);
auto lower = (triangle == Triangle::kLower);
- status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
+ status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
n, n, c_ld, c_offset, c_buffer,
- c_rotated, false, false, upper, lower, false, program);
+ program, false, c_rotated, false, upper, lower, false);
if (ErrorIn(status)) { return status; }
// Successfully finished the computation
diff --git a/src/routines/level3/xsyrk.cc b/src/routines/level3/xsyrk.cc
index bb952410..0bafe703 100644
--- a/src/routines/level3/xsyrk.cc
+++ b/src/routines/level3/xsyrk.cc
@@ -75,26 +75,35 @@ StatusCode Xsyrk<T>::DoSyrk(const Layout layout, const Triangle triangle, const
// Decides which kernel to run: the upper-triangular or lower-triangular version
auto kernel_name = (triangle == Triangle::kUpper) ? "XgemmUpper" : "XgemmLower";
- // Allocates space on the device for padded and/or transposed input and output matrices.
+ // The padded/transposed input/output matrices: if memory allocation fails, throw an exception
try {
- auto temp_a = Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
- auto temp_c = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
// Loads the program from the database
auto& program = GetProgramFromCache();
- // Runs the pre-processing kernel. This transposes the matrix A, but also pads zeros to
- // fill it up until it reaches a certain multiple of size (kernel parameter dependent).
- status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
- n_ceiled, k_ceiled, n_ceiled, 0, temp_a,
- a_rotated, false, true, false, false, false, program);
- if (ErrorIn(status)) { return status; }
+ // Determines whether or not temporary matrices are needed
+ auto a_no_temp = a_one == n_ceiled && a_two == k_ceiled && a_ld == n_ceiled && a_offset == 0 &&
+ a_rotated == false;
+
+ // Creates the temporary matrices
+ auto a_temp = (a_no_temp) ? a_buffer : Buffer(context_, CL_MEM_READ_WRITE, k_ceiled*n_ceiled*sizeof(T));
+ auto c_temp = Buffer(context_, CL_MEM_READ_WRITE, n_ceiled*n_ceiled*sizeof(T));
+
+ // Runs the pre-processing kernel for matrix A. This transposes the matrix, but also pads zeros
+ // to fill it up until it reaches a certain multiple of size (kernel parameter dependent). In
+ // case nothing has to be done, these kernels can be skipped.
+ if (!a_no_temp) {
+ status = PadCopyTransposeMatrix(a_one, a_two, a_ld, a_offset, a_buffer,
+ n_ceiled, k_ceiled, n_ceiled, 0, a_temp,
+ program, true, a_rotated, false);
+ if (ErrorIn(status)) { return status; }
+ }
// Furthermore, also creates a (possibly padded) copy of matrix C, since it is not allowed to
// modify the other triangle.
status = PadCopyTransposeMatrix(n, n, c_ld, c_offset, c_buffer,
- n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
- c_rotated, false, true, false, false, false, program);
+ n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
+ program, true, c_rotated, false);
if (ErrorIn(status)) { return status; }
// Retrieves the XgemmUpper or XgemmLower kernel from the compiled binary
@@ -106,9 +115,9 @@ StatusCode Xsyrk<T>::DoSyrk(const Layout layout, const Triangle triangle, const
kernel.SetArgument(1, static_cast<int>(k_ceiled));
kernel.SetArgument(2, alpha);
kernel.SetArgument(3, beta);
- kernel.SetArgument(4, temp_a());
- kernel.SetArgument(5, temp_a());
- kernel.SetArgument(6, temp_c());
+ kernel.SetArgument(4, a_temp());
+ kernel.SetArgument(5, a_temp());
+ kernel.SetArgument(6, c_temp());
// Computes the global and local thread sizes
auto global = std::vector<size_t>{
@@ -124,9 +133,9 @@ StatusCode Xsyrk<T>::DoSyrk(const Layout layout, const Triangle triangle, const
// Runs the post-processing kernel
auto upper = (triangle == Triangle::kUpper);
auto lower = (triangle == Triangle::kLower);
- status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, temp_c,
+ status = PadCopyTransposeMatrix(n_ceiled, n_ceiled, n_ceiled, 0, c_temp,
n, n, c_ld, c_offset, c_buffer,
- c_rotated, false, false, upper, lower, false, program);
+ program, false, c_rotated, false, upper, lower, false);
if (ErrorIn(status)) { return status; }
// Successfully finished the computation