summaryrefslogtreecommitdiff
path: root/src/tuning
diff options
context:
space:
mode:
authorCedric Nugteren <web@cedricnugteren.nl>2018-07-29 15:07:51 +0200
committerKoichi Akabe <vbkaisetsu@gmail.com>2018-12-18 13:59:26 +0900
commit1f0cd618247971f0803aff94ddf795d9e3d19428 (patch)
tree7a0a01742d59f633937c3b6dd760a9e51a69c9bf /src/tuning
parent301dc280dfe75ff3c8b219f64aea83a6bf2f0c8d (diff)
Added first version of a tuner for the ConvGemm direct kernel
Diffstat (limited to 'src/tuning')
-rw-r--r--src/tuning/kernels/xconvgemm.cpp38
-rw-r--r--src/tuning/kernels/xconvgemm.hpp186
-rw-r--r--src/tuning/tuning.cpp10
-rw-r--r--src/tuning/tuning.hpp7
4 files changed, 239 insertions, 2 deletions
diff --git a/src/tuning/kernels/xconvgemm.cpp b/src/tuning/kernels/xconvgemm.cpp
new file mode 100644
index 00000000..15dfe829
--- /dev/null
+++ b/src/tuning/kernels/xconvgemm.cpp
@@ -0,0 +1,38 @@
+
+// =================================================================================================
+// This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This
+// project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max-
+// width of 100 characters per line.
+//
+// Author(s):
+// Cedric Nugteren <www.cedricnugteren.nl>
+//
+// This file uses the auto-tuner to tune the convgemm kernels.
+//
+// =================================================================================================
+
+#include "tuning/kernels/xconvgemm.hpp"
+
+// Shortcuts to the clblast namespace
+using half = clblast::half;
+using float2 = clblast::float2;
+using double2 = clblast::double2;
+
+// Function to tune a specific variation V (not within the clblast namespace)
+template <int V>
+void StartVariation(int argc, char *argv[]) {
+ const auto command_line_args = clblast::RetrieveCommandLineArguments(argc, argv);
+ switch(clblast::GetPrecision(command_line_args)) {
+ case clblast::Precision::kHalf: clblast::Tuner<half>(argc, argv, V, clblast::XConvGemmGetTunerDefaults, clblast::XConvGemmGetTunerSettings<half>, clblast::XConvGemmTestValidArguments<half>, clblast::XConvGemmSetConstraints, clblast::XConvGemmComputeLocalMemSize<half>, clblast::XConvGemmSetArguments<half>); break;
+ case clblast::Precision::kSingle: clblast::Tuner<float>(argc, argv, V, clblast::XConvGemmGetTunerDefaults, clblast::XConvGemmGetTunerSettings<float>, clblast::XConvGemmTestValidArguments<float>, clblast::XConvGemmSetConstraints, clblast::XConvGemmComputeLocalMemSize<float>, clblast::XConvGemmSetArguments<float>); break;
+ case clblast::Precision::kDouble: clblast::Tuner<double>(argc, argv, V, clblast::XConvGemmGetTunerDefaults, clblast::XConvGemmGetTunerSettings<double>, clblast::XConvGemmTestValidArguments<double>, clblast::XConvGemmSetConstraints, clblast::XConvGemmComputeLocalMemSize<double>, clblast::XConvGemmSetArguments<double>); break;
+ }
+}
+
+// Main function (not within the clblast namespace)
+int main(int argc, char *argv[]) {
+ StartVariation<1>(argc, argv);
+ return 0;
+}
+
+// =================================================================================================
diff --git a/src/tuning/kernels/xconvgemm.hpp b/src/tuning/kernels/xconvgemm.hpp
new file mode 100644
index 00000000..83c93860
--- /dev/null
+++ b/src/tuning/kernels/xconvgemm.hpp
@@ -0,0 +1,186 @@
+
+// =================================================================================================
+// This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This
+// project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max-
+// width of 100 characters per line.
+//
+// Author(s):
+// Cedric Nugteren <www.cedricnugteren.nl>
+//
+// This file uses the auto-tuner to tune the ConvGemm kernels. These kernels are based on the GEMM
+// direct kernel and will use those parameters, this tuner is just optional to use for advanced
+// users.
+//
+// =================================================================================================
+
+#include <string>
+#include <vector>
+
+#include "utilities/utilities.hpp"
+#include "tuning/tuning.hpp"
+
+namespace clblast {
+// =================================================================================================
+
+// Helper functions
+template <typename T>
+size_t OutputHeight(const Arguments<T> &args) {
+ const auto size = args.height + 2 * args.pad_h;
+ const auto padding = args.dilation_h * (args.kernel_h - 1) + 1;
+ if (size >= padding) { return (size - padding) / args.stride_h + 1; }
+ return 1;
+}
+template <typename T>
+size_t OutputWidth(const Arguments<T> &args) {
+ const auto size = args.width + 2 * args.pad_w;
+ const auto padding = args.dilation_w * (args.kernel_w - 1) + 1;
+ if (size >= padding) { return (size - padding) / args.stride_w + 1; }
+ return 1;
+}
+
+// Settings for this kernel (default command-line arguments)
+TunerDefaults XConvGemmGetTunerDefaults(const int) {
+ auto settings = TunerDefaults();
+ settings.options = {kArgChannels, kArgHeight, kArgWidth, kArgKernelH, kArgKernelW,
+ kArgNumKernels, kArgBatchCount, kArgFraction};
+ settings.channels = 32;
+ settings.height = 64;
+ settings.width = 64;
+ settings.kernel_h = 3;
+ settings.kernel_w = 3;
+ settings.num_kernels = 32;
+ settings.default_batch_count = 16;
+ settings.default_fraction = 1.0;
+ settings.default_num_runs = 2;
+ return settings;
+}
+
+// Settings for this kernel (general)
+template <typename T>
+TunerSettings XConvGemmGetTunerSettings(const int, const Arguments<T> &args) {
+ auto settings = TunerSettings();
+
+ // Identification of the kernel
+ settings.kernel_family = "xconvgemm";
+ settings.kernel_name = "Xconvgemm";
+ settings.sources =
+"#define ROUTINE_CONVGEMM"
+#include "../src/kernels/level3/xgemm_direct_part1.opencl"
+#include "../src/kernels/level3/xgemm_direct_part2.opencl"
+#include "../src/kernels/level3/xgemm_direct_part3.opencl"
+#include "../src/kernels/levelx/xconvgemm_part1.opencl"
+#include "../src/kernels/levelx/xconvgemm_part2.opencl"
+ ;
+
+ // Helper variables
+ const auto patch_size = args.kernel_h * args.kernel_w * args.channels;
+ const auto num_patches = OutputHeight(args) * OutputWidth(args);
+
+ // Buffer sizes
+ settings.size_a = args.batch_count * args.channels * args.height * args.width;
+ settings.size_b = args.num_kernels * args.channels * args.kernel_h * args.kernel_w;
+ settings.size_a = args.batch_count * args.num_kernels * OutputHeight(args) * OutputWidth(args);
+
+ // Inputs and outputs IDs (X:0, Y:1, A:2, B:3, C:4, temp:5)
+ settings.inputs = {2, 3, 4};
+ settings.outputs = {4};
+
+ // Sets the base thread configuration
+ settings.global_size = {num_patches, args.num_kernels};
+ settings.global_size_ref = settings.global_size;
+ settings.local_size = {1, 1};
+ settings.local_size_ref = {8, 8};
+
+ // Transforms the thread configuration based on the parameters
+ settings.mul_local = {{"MDIMCD", "NDIMCD"}};
+ settings.mul_global = {{"MDIMCD", "NDIMCD"}};
+ settings.div_global = {{"WGD", "WGD"}};
+
+ // Sets the tuning parameters and their possible values
+ settings.parameters = {
+ {"WGD", {8, 16, 32}},
+ {"MDIMCD", {8, 16, 32}},
+ {"NDIMCD", {8, 16, 32}},
+ {"MDIMAD", {8, 16, 32}},
+ {"NDIMBD", {8, 16, 32}},
+ {"KWID", {1}},
+ {"VWMD", {1, 2, 4, 8}},
+ {"VWND", {1, 2, 4, 8}},
+ {"PADA", {0}},
+ {"PADB", {0}},
+ };
+
+ // Describes how to compute the performance metrics
+ settings.metric_amount = args.batch_count * 2 * num_patches * args.num_kernels * patch_size;
+ settings.performance_unit = "GFLOPS";
+
+ return settings;
+}
+
+// Tests for valid arguments
+template <typename T>
+void XConvGemmTestValidArguments(const int, const Arguments<T> &) { }
+std::vector<Constraint> XConvGemmSetConstraints(const int) {
+ auto constraints = std::vector<Constraint>();
+ auto MultipleOfX = [] (std::vector<size_t> v) { return IsMultiple(v[0], v[1]); };
+ auto MultipleOfXMulY = [] (std::vector<size_t> v) { return IsMultiple(v[0], v[1]*v[2]); };
+ auto MultipleOfXMulYDivZ = [] (std::vector<size_t> v) { return IsMultiple(v[0], (v[1]*v[2])/v[3]); };
+ // Requirement for unrolling the WGD loop
+ constraints.push_back({MultipleOfX, {"WGD", "KWID"}});
+ // Required for integer MWID and NWID
+ constraints.push_back({MultipleOfXMulY, {"WGD", "MDIMCD", "VWMD"}});
+ constraints.push_back({MultipleOfXMulY, {"WGD", "NDIMCD", "VWND"}});
+ // Required for integer MWIAD and NWIBD
+ constraints.push_back({MultipleOfXMulY, {"WGD", "MDIMAD", "VWMD"}});
+ constraints.push_back({MultipleOfXMulY, {"WGD", "NDIMBD", "VWND"}});
+ // WGD has to be a multiple of KDIMAD = ((MDIMCD*NDIMCD)/(MDIMAD)) and KDIMBD = (...)
+ constraints.push_back({MultipleOfXMulYDivZ, {"WGD", "MDIMCD", "NDIMCD", "MDIMAD"}});
+ constraints.push_back({MultipleOfXMulYDivZ, {"WGD", "MDIMCD", "NDIMCD", "NDIMBD"}});
+
+ return constraints;
+}
+template <typename T>
+LocalMemSizeInfo XConvGemmComputeLocalMemSize(const int) {
+ return {
+ [] (std::vector<size_t> v) -> size_t {
+ return GetBytes(PrecisionValue<T>()) * ((v[0]*(v[0] + v[1]) + v[0]*(v[0] + v[2])));
+ },
+ {"WGD", "PADA", "PADB"}
+ };
+}
+
+// Sets the kernel's arguments
+template <typename T>
+void XConvGemmSetArguments(const int, Kernel &kernel, const Arguments<T> &args, std::vector<Buffer<T>>& buffers) {
+ const auto output_h = OutputHeight(args);
+ const auto output_w = OutputWidth(args);
+ const auto patch_size = args.kernel_h * args.kernel_w * args.channels;
+ const auto num_patches = output_h * output_w;
+ const auto result_stride = args.num_kernels * output_h * output_w;
+ kernel.SetArgument(0, static_cast<int>(num_patches));
+ kernel.SetArgument(1, static_cast<int>(args.num_kernels));
+ kernel.SetArgument(2, static_cast<int>(patch_size));
+ kernel.SetArgument(3, buffers[3]()); // 3 == B matrix ==> kernel buffer
+ kernel.SetArgument(4, 0); // c_offset
+ kernel.SetArgument(5, buffers[4]()); // 4 == C matrix ==> result buffer
+ kernel.SetArgument(6, 0); // c_offset
+ kernel.SetArgument(7, static_cast<int>(result_stride));
+ kernel.SetArgument(8, buffers[2]()); // 2 == A matrix ==> image buffer
+ kernel.SetArgument(9, 0); // c_offset
+ kernel.SetArgument(10, static_cast<int>(args.height));
+ kernel.SetArgument(11, static_cast<int>(args.width));
+ kernel.SetArgument(12, static_cast<int>(args.channels));
+ kernel.SetArgument(13, static_cast<int>(args.kernel_h));
+ kernel.SetArgument(14, static_cast<int>(args.kernel_w));
+ kernel.SetArgument(15, 0); // pad_h
+ kernel.SetArgument(16, 0); // pad_w
+ kernel.SetArgument(17, 1); // stride_h
+ kernel.SetArgument(18, 1); // stride_w
+ kernel.SetArgument(19, 1); // dilation_h
+ kernel.SetArgument(20, 1); // dilation_w
+ kernel.SetArgument(21, static_cast<int>(output_h));
+ kernel.SetArgument(22, static_cast<int>(output_w));
+}
+
+// =================================================================================================
+} // namespace clblast
diff --git a/src/tuning/tuning.cpp b/src/tuning/tuning.cpp
index d382fb18..f76af774 100644
--- a/src/tuning/tuning.cpp
+++ b/src/tuning/tuning.cpp
@@ -122,8 +122,14 @@ void Tuner(int argc, char* argv[], const int V,
if (o == kArgM) { args.m = GetArgument(command_line_args, help, kArgM, defaults.default_m); }
if (o == kArgN) { args.n = GetArgument(command_line_args, help, kArgN, defaults.default_n); }
if (o == kArgK) { args.k = GetArgument(command_line_args, help, kArgK, defaults.default_k); }
- if (o == kArgAlpha) { args.alpha = GetArgument(command_line_args, help, kArgAlpha, GetScalar<T>()); }
- if (o == kArgBeta) { args.beta = GetArgument(command_line_args, help, kArgBeta, GetScalar<T>()); }
+ if (o == kArgChannels) { args.channels = GetArgument(command_line_args, help, kArgChannels, defaults.channels); }
+ if (o == kArgHeight) { args.height = GetArgument(command_line_args, help, kArgHeight, defaults.height); }
+ if (o == kArgWidth) { args.width = GetArgument(command_line_args, help, kArgWidth, defaults.width); }
+ if (o == kArgKernelH) { args.kernel_h = GetArgument(command_line_args, help, kArgKernelH, defaults.kernel_h); }
+ if (o == kArgKernelW) { args.kernel_w = GetArgument(command_line_args, help, kArgKernelW, defaults.kernel_w); }
+ if (o == kArgNumKernels) { args.num_kernels = GetArgument(command_line_args, help, kArgNumKernels, defaults.num_kernels); }
+ if (o == kArgAlpha) { args.alpha = GetArgument(command_line_args, help, kArgAlpha, GetScalar<T>()); }
+ if (o == kArgBeta) { args.beta = GetArgument(command_line_args, help, kArgBeta, GetScalar<T>()); }
if (o == kArgBatchCount) { args.batch_count = GetArgument(command_line_args, help, kArgBatchCount, defaults.default_batch_count); }
}
args.fraction = GetArgument(command_line_args, help, kArgFraction, defaults.default_fraction);
diff --git a/src/tuning/tuning.hpp b/src/tuning/tuning.hpp
index 37a042ff..61cc3bda 100644
--- a/src/tuning/tuning.hpp
+++ b/src/tuning/tuning.hpp
@@ -41,6 +41,13 @@ struct TunerDefaults {
size_t default_m = 1;
size_t default_n = 1;
size_t default_k = 1;
+ size_t channels = 1;
+ size_t height = 1;
+ size_t width = 1;
+ size_t kernel_h = 3;
+ size_t kernel_w = 3;
+ size_t num_kernels = 1;
+ size_t batch_count = 1;
// Other defaults
size_t default_batch_count = 1;