diff options
Diffstat (limited to 'test/performance')
-rw-r--r-- | test/performance/client.cc | 295 | ||||
-rw-r--r-- | test/performance/client.h | 85 | ||||
-rw-r--r-- | test/performance/graphs/common.r | 189 | ||||
-rw-r--r-- | test/performance/graphs/xaxpy.r | 96 | ||||
-rwxr-xr-x | test/performance/graphs/xgemm.r | 94 | ||||
-rw-r--r-- | test/performance/graphs/xsymm.r | 94 | ||||
-rw-r--r-- | test/performance/routines/xaxpy.cc | 97 | ||||
-rw-r--r-- | test/performance/routines/xgemm.cc | 115 | ||||
-rw-r--r-- | test/performance/routines/xsymm.cc | 115 |
9 files changed, 1180 insertions, 0 deletions
diff --git a/test/performance/client.cc b/test/performance/client.cc new file mode 100644 index 00000000..ddaea0e1 --- /dev/null +++ b/test/performance/client.cc @@ -0,0 +1,295 @@ + +// ================================================================================================= +// 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 implements the common functions for the client-test environment. +// +// ================================================================================================= + +#include "performance/client.h" + +#include <string> +#include <vector> +#include <algorithm> +#include <chrono> + +namespace clblast { +// ================================================================================================= + +// This is the vector-vector variant of the set-up/tear-down client routine. +template <typename T> +void ClientXY(int argc, char *argv[], Routine2<T> client_routine, + const std::vector<std::string> &options) { + + // Simple command line argument parser with defaults + auto args = ParseArguments<T>(argc, argv, options); + if (args.print_help) { return; } + + // Prints the header of the output table + PrintTableHeader(args.silent, options); + + // Initializes OpenCL and the libraries + auto platform = Platform(args.platform_id); + auto device = Device(platform, kDeviceType, args.device_id); + auto context = Context(device); + auto queue = CommandQueue(context, device); + if (args.compare_clblas) { clblasSetup(); } + + // Iterates over all "num_step" values jumping by "step" each time + auto s = size_t{0}; + while(true) { + + // Computes the data sizes + auto x_size = args.n*args.x_inc + args.x_offset; + auto y_size = args.n*args.y_inc + args.y_offset; + + // Populates input host vectors with random data + std::vector<T> x_source(x_size); + std::vector<T> y_source(y_size); + PopulateVector(x_source); + PopulateVector(y_source); + + // Creates the vectors on the device + auto x_buffer = Buffer(context, CL_MEM_READ_WRITE, x_size*sizeof(T)); + auto y_buffer = Buffer(context, CL_MEM_READ_WRITE, y_size*sizeof(T)); + x_buffer.WriteBuffer(queue, x_size*sizeof(T), x_source); + y_buffer.WriteBuffer(queue, y_size*sizeof(T), y_source); + + // Runs the routine-specific code + client_routine(args, x_buffer, y_buffer, queue); + + // Makes the jump to the next step + ++s; + if (s >= args.num_steps) { break; } + args.n += args.step; + } + + // Cleans-up and returns + if (args.compare_clblas) { clblasTeardown(); } +} + +// Compiles the above function +template void ClientXY<float>(int, char **, Routine2<float>, const std::vector<std::string>&); +template void ClientXY<double>(int, char **, Routine2<double>, const std::vector<std::string>&); +template void ClientXY<float2>(int, char **, Routine2<float2>, const std::vector<std::string>&); +template void ClientXY<double2>(int, char **, Routine2<double2>, const std::vector<std::string>&); + +// ================================================================================================= + +// This is the matrix-matrix-matrix variant of the set-up/tear-down client routine. +template <typename T> +void ClientABC(int argc, char *argv[], Routine3<T> client_routine, + const std::vector<std::string> &options) { + + // Simple command line argument parser with defaults + auto args = ParseArguments<T>(argc, argv, options); + if (args.print_help) { return; } + + // Prints the header of the output table + PrintTableHeader(args.silent, options); + + // Initializes OpenCL and the libraries + auto platform = Platform(args.platform_id); + auto device = Device(platform, kDeviceType, args.device_id); + auto context = Context(device); + auto queue = CommandQueue(context, device); + if (args.compare_clblas) { clblasSetup(); } + + // Computes whether or not the matrices are transposed. Note that we assume a default of + // column-major and no-transpose. If one of them is different (but not both), then rotated + // is considered true. + auto a_rotated = (args.layout == Layout::kColMajor && args.a_transpose == Transpose::kYes) || + (args.layout == Layout::kRowMajor && args.a_transpose == Transpose::kNo); + auto b_rotated = (args.layout == Layout::kColMajor && args.b_transpose == Transpose::kYes) || + (args.layout == Layout::kRowMajor && args.b_transpose == Transpose::kNo); + auto c_rotated = (args.layout == Layout::kRowMajor); + + // Iterates over all "num_step" values jumping by "step" each time + auto s = size_t{0}; + while(true) { + + // Computes the data sizes + auto a_two = (a_rotated) ? args.m : args.k; + auto b_two = (b_rotated) ? args.k : args.n; + auto c_two = (c_rotated) ? args.m : args.n; + auto a_size = a_two * args.a_ld + args.a_offset; + auto b_size = b_two * args.b_ld + args.b_offset; + auto c_size = c_two * args.c_ld + args.c_offset; + + // Populates input host matrices with random data + std::vector<T> a_source(a_size); + std::vector<T> b_source(b_size); + std::vector<T> c_source(c_size); + PopulateVector(a_source); + PopulateVector(b_source); + PopulateVector(c_source); + + // Creates the matrices on the device + auto a_buffer = Buffer(context, CL_MEM_READ_WRITE, a_size*sizeof(T)); + auto b_buffer = Buffer(context, CL_MEM_READ_WRITE, b_size*sizeof(T)); + auto c_buffer = Buffer(context, CL_MEM_READ_WRITE, c_size*sizeof(T)); + a_buffer.WriteBuffer(queue, a_size*sizeof(T), a_source); + b_buffer.WriteBuffer(queue, b_size*sizeof(T), b_source); + c_buffer.WriteBuffer(queue, c_size*sizeof(T), c_source); + + // Runs the routine-specific code + client_routine(args, a_buffer, b_buffer, c_buffer, queue); + + // Makes the jump to the next step + ++s; + if (s >= args.num_steps) { break; } + args.m += args.step; + args.n += args.step; + args.k += args.step; + args.a_ld += args.step; + args.b_ld += args.step; + args.c_ld += args.step; + } + + // Cleans-up and returns + if (args.compare_clblas) { clblasTeardown(); } +} + +// Compiles the above function +template void ClientABC<float>(int, char **, Routine3<float>, const std::vector<std::string>&); +template void ClientABC<double>(int, char **, Routine3<double>, const std::vector<std::string>&); +template void ClientABC<float2>(int, char **, Routine3<float2>, const std::vector<std::string>&); +template void ClientABC<double2>(int, char **, Routine3<double2>, const std::vector<std::string>&); + +// ================================================================================================= + +// Parses all arguments available for the CLBlast client testers. Some arguments might not be +// applicable, but are searched for anyway to be able to create one common argument parser. All +// arguments have a default value in case they are not found. +template <typename T> +Arguments<T> ParseArguments(int argc, char *argv[], const std::vector<std::string> &options) { + auto args = Arguments<T>{}; + auto help = std::string{"Options given/available:\n"}; + + // These are the options which are not for every client: they are optional + for (auto &o: options) { + + // Data-sizes + if (o == kArgM) { args.m = args.k = GetArgument(argc, argv, help, kArgM, 512UL); } + if (o == kArgN) { args.n = GetArgument(argc, argv, help, kArgN, 512UL); } + if (o == kArgK) { args.k = GetArgument(argc, argv, help, kArgK, 512UL); } + + // Data-layouts + if (o == kArgLayout) { args.layout = GetArgument(argc, argv, help, kArgLayout, Layout::kRowMajor); } + if (o == kArgATransp) { args.a_transpose = GetArgument(argc, argv, help, kArgATransp, Transpose::kNo); } + if (o == kArgBTransp) { args.b_transpose = GetArgument(argc, argv, help, kArgBTransp, Transpose::kNo); } + if (o == kArgSide) { args.side = GetArgument(argc, argv, help, kArgSide, Side::kLeft); } + if (o == kArgTriangle) { args.triangle = GetArgument(argc, argv, help, kArgTriangle, Triangle::kUpper); } + + // Vector arguments + if (o == kArgXInc) { args.x_inc = GetArgument(argc, argv, help, kArgXInc, size_t{1}); } + if (o == kArgYInc) { args.y_inc = GetArgument(argc, argv, help, kArgYInc, size_t{1}); } + if (o == kArgXOffset) { args.x_offset = GetArgument(argc, argv, help, kArgXOffset, size_t{0}); } + if (o == kArgYOffset) { args.y_offset = GetArgument(argc, argv, help, kArgYOffset, size_t{0}); } + + // Matrix arguments + if (o == kArgALeadDim) { args.a_ld = GetArgument(argc, argv, help, kArgALeadDim, args.k); } + if (o == kArgBLeadDim) { args.b_ld = GetArgument(argc, argv, help, kArgBLeadDim, args.n); } + if (o == kArgCLeadDim) { args.c_ld = GetArgument(argc, argv, help, kArgCLeadDim, args.n); } + if (o == kArgAOffset) { args.a_offset = GetArgument(argc, argv, help, kArgAOffset, size_t{0}); } + if (o == kArgBOffset) { args.b_offset = GetArgument(argc, argv, help, kArgBOffset, size_t{0}); } + if (o == kArgCOffset) { args.c_offset = GetArgument(argc, argv, help, kArgCOffset, size_t{0}); } + + // Scalar values + if (o == kArgAlpha) { args.alpha = GetArgument(argc, argv, help, kArgAlpha, GetScalar<T>()); } + if (o == kArgBeta) { args.beta = GetArgument(argc, argv, help, kArgBeta, GetScalar<T>()); } + } + + // These are the options common to all routines + args.platform_id = GetArgument(argc, argv, help, kArgPlatform, size_t{0}); + args.device_id = GetArgument(argc, argv, help, kArgDevice, size_t{0}); + args.precision = GetArgument(argc, argv, help, kArgPrecision, Precision::kSingle); + args.compare_clblas = GetArgument(argc, argv, help, kArgCompareclblas, true); + args.step = GetArgument(argc, argv, help, kArgStepSize, size_t{1}); + args.num_steps = GetArgument(argc, argv, help, kArgNumSteps, size_t{0}); + args.num_runs = GetArgument(argc, argv, help, kArgNumRuns, size_t{10}); + args.print_help = CheckArgument(argc, argv, help, kArgHelp); + args.silent = CheckArgument(argc, argv, help, kArgQuiet); + args.no_abbrv = CheckArgument(argc, argv, help, kArgNoAbbreviations); + + // Prints the chosen (or defaulted) arguments to screen. This also serves as the help message, + // which is thus always displayed (unless silence is specified). + if (!args.silent) { fprintf(stdout, "%s\n", help.c_str()); } + + // Returns the arguments + return args; +} + +// ================================================================================================= + +// Creates a vector of timing results, filled with execution times of the 'main computation'. The +// timing is performed using the milliseconds chrono functions. The function returns the minimum +// value found in the vector of timing results. The return value is in milliseconds. +double TimedExecution(const size_t num_runs, std::function<void()> main_computation) { + auto timings = std::vector<double>(num_runs); + for (auto &timing: timings) { + auto start_time = std::chrono::steady_clock::now(); + + // Executes the main computation + main_computation(); + + // Records and stores the end-time + auto elapsed_time = std::chrono::steady_clock::now() - start_time; + timing = std::chrono::duration<double,std::milli>(elapsed_time).count(); + } + return *std::min_element(timings.begin(), timings.end()); +} + +// ================================================================================================= + +// Prints the header of the performance table +void PrintTableHeader(const bool silent, const std::vector<std::string> &args) { + if (!silent) { + for (auto i=size_t{0}; i<args.size(); ++i) { fprintf(stdout, "%9s ", ""); } + fprintf(stdout, " | <-- CLBlast --> | <-- clBLAS --> |\n"); + } + for (auto &argument: args) { fprintf(stdout, "%9s;", argument.c_str()); } + fprintf(stdout, "%9s;%9s;%9s;%9s;%9s;%9s\n", + "ms_1", "GFLOPS_1", "GBs_1", "ms_2", "GFLOPS_2", "GBs_2"); +} + +// Print a performance-result row +void PrintTableRow(const std::vector<size_t> &args_int, const std::vector<std::string> &args_string, + const bool no_abbrv, const double ms_clblast, const double ms_clblas, + const unsigned long long flops, const unsigned long long bytes) { + + // Computes the GFLOPS and GB/s metrics + auto gflops_clblast = (ms_clblast != 0.0) ? (flops*1e-6)/ms_clblast : 0; + auto gflops_clblas = (ms_clblas != 0.0) ? (flops*1e-6)/ms_clblas: 0; + auto gbs_clblast = (ms_clblast != 0.0) ? (bytes*1e-6)/ms_clblast : 0; + auto gbs_clblas = (ms_clblas != 0.0) ? (bytes*1e-6)/ms_clblas: 0; + + // Outputs the argument values + for (auto &argument: args_int) { + if (!no_abbrv && argument >= 1024*1024 && IsMultiple(argument, 1024*1024)) { + fprintf(stdout, "%8luM;", argument/(1024*1024)); + } + else if (!no_abbrv && argument >= 1024 && IsMultiple(argument, 1024)) { + fprintf(stdout, "%8luK;", argument/1024); + } + else { + fprintf(stdout, "%9lu;", argument); + } + } + for (auto &argument: args_string) { + fprintf(stdout, "%9s;", argument.c_str()); + } + + // Outputs the performance numbers + fprintf(stdout, "%9.2lf;%9.1lf;%9.1lf;%9.2lf;%9.1lf;%9.1lf\n", + ms_clblast, gflops_clblast, gbs_clblast, + ms_clblas, gflops_clblas, gbs_clblas); +} + +// ================================================================================================= +} // namespace clblast diff --git a/test/performance/client.h b/test/performance/client.h new file mode 100644 index 00000000..2b9991fe --- /dev/null +++ b/test/performance/client.h @@ -0,0 +1,85 @@ + +// ================================================================================================= +// 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 provides common function declarations to be used with the test clients. +// +// ================================================================================================= + +#ifndef CLBLAST_TEST_PERFORMANCE_CLIENT_H_ +#define CLBLAST_TEST_PERFORMANCE_CLIENT_H_ + +#include <string> +#include <vector> + +// The libraries to test +#include <clBLAS.h> +#include "clblast.h" + +#include "internal/utilities.h" + +namespace clblast { +// ================================================================================================= + +// Types of devices to consider +const cl_device_type kDeviceType = CL_DEVICE_TYPE_ALL; + +// ================================================================================================= + +// Shorthand for a BLAS routine with 2 or 3 OpenCL buffers as argument +template <typename T> +using Routine2 = std::function<void(const Arguments<T>&, + const Buffer&, const Buffer&, + CommandQueue&)>; +template <typename T> +using Routine3 = std::function<void(const Arguments<T>&, + const Buffer&, const Buffer&, const Buffer&, + CommandQueue&)>; + +// ================================================================================================= + +// These are the main client functions, setting-up arguments, matrices, OpenCL buffers, etc. After +// set-up, they call the client routine, passed as argument to this function. +template <typename T> +void ClientXY(int argc, char *argv[], Routine2<T> client_routine, + const std::vector<std::string> &options); +template <typename T> +void ClientABC(int argc, char *argv[], Routine3<T> client_routine, + const std::vector<std::string> &options); + +// ================================================================================================= + +// Parses all command-line arguments, filling in the arguments structure. If no command-line +// argument is given for a particular argument, it is filled in with a default value. +template <typename T> +Arguments<T> ParseArguments(int argc, char *argv[], const std::vector<std::string> &options); + +// Retrieves only the precision command-line argument, since the above function is templated based +// on the precision +Precision GetPrecision(int argc, char *argv[]); + +// ================================================================================================= + +// Runs a function a given number of times and returns the execution time of the shortest instance +double TimedExecution(const size_t num_runs, std::function<void()> main_computation); + +// ================================================================================================= + +// Prints the header of a performance-data table +void PrintTableHeader(const bool silent, const std::vector<std::string> &args); + +// Prints a row of performance data, including results of two libraries +void PrintTableRow(const std::vector<size_t> &args_int, const std::vector<std::string> &args_string, + const bool abbreviations, const double ms_clblast, const double ms_clblas, + const unsigned long long flops, const unsigned long long bytes); + +// ================================================================================================= +} // namespace clblast + +// CLBLAST_TEST_PERFORMANCE_CLIENT_H_ +#endif diff --git a/test/performance/graphs/common.r b/test/performance/graphs/common.r new file mode 100644 index 00000000..4572e559 --- /dev/null +++ b/test/performance/graphs/common.r @@ -0,0 +1,189 @@ + +# ================================================================================================== +# This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This +# project 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 implements the common performance scripts, such as creating a graph. +# +# ================================================================================================== + +# Colours +black = "#000000" +grey = "#888888" +purplish = "#550077" # [ 85, 0,119] lumi=26 +blueish = "#4765b1" # [ 71,101,177] lumi=100 +redish = "#d67568" # [214,117,104] lumi=136 +greenish = "#9bd4ca" # [155,212,202] lumi=199 +colourset = c(blueish, redish, greenish, purplish) + +# Sets the graph markers (circles, triangles, etc.) +pchs = c(15, 18, 17, 12) + +# Other constants +kilo = 1024 +mega = 1024*1024 + +# R options +options("width"=170) + +# ================================================================================================== + +# Constants +num_runs <- 4 +devices <- c("-platform","-device") +options_string <- "-q -no_abbrv" +library_names <- c("CLBlast", "clBLAS") + +# Command-line arguments +command_line <- commandArgs(trailingOnly=TRUE) +if (length(command_line) != 2) { + print("Usage for device Z on platform Y: Rscript xxxxx.r Y Z") + quit() +} +platform_id <- command_line[1] +device_id <- command_line[2] + +# Selects the device +devices_values <- c(platform_id, device_id) +devices_string <- paste(devices, devices_values, collapse=" ") + +# ================================================================================================== + +# The main function +main <- function(routine_name, precision, test_names, test_values, + test_xlabels, test_xaxis, metric_gflops) { + + # Names + display_name <- toupper(routine_name) + if (precision == 16) { display_name <- gsub("^X","H",display_name); } + if (precision == 32) { display_name <- gsub("^X","S",display_name); } + if (precision == 64) { display_name <- gsub("^X","D",display_name); } + if (precision == 3232) { display_name <- gsub("^X","C",display_name); } + if (precision == 6464) { display_name <- gsub("^X","Z",display_name); } + executable <- paste("./client_", routine_name, sep="") + + # Configures the outputfile + pdf(paste(display_name, ".pdf", sep=""), height=8, width=13) + par(mfrow=c(2, 3)) + par(oma=c(0, 0, 0, 0)) + par(mar=c(4.6, 4.4, 1.5, 0)) # bottom, left, top, right [c(5.1, 4.1, 4.1, 2.1)] + par(mgp=c(2.8, 0.6, 0)) # location of xlab/ylab, tick-mark labels, tick marks [c(3, 1, 0)] + + # Loops over the test-cases + for (test_id in 1:length(test_names)) { + params_values <- test_values[[test_id]] + + # Loops over the commands within a single list (within a case) + for (command_id in 1:length(params_values)) { + + # Runs the client and captures the result + params_string <- paste(parameters, params_values[[command_id]], collapse=" ") + arguments <- paste(devices_string, params_string, options_string, sep=" ") + result_string <- system2(command=executable, args=arguments, stdout=TRUE) + + # Reads the result into a dataframe + command_db <- read.csv(text=result_string, sep=";") + + # Append the results to the final dataframe + if (command_id == 1) { + db <- command_db + } else { + db <- rbind(db, command_db) + } + } + print(db) + + # Sets the values on the x-axis and their labels (test dependent) + if (is.character(test_xaxis[[test_id]][[1]])) { + xdata <- db[,test_xaxis[[test_id]][[1]]] + xtics <- xdata + log_scale <- test_xaxis[[test_id]][[2]] + } + else { + xdata <- test_xaxis[[test_id]][[1]] + xtics <- test_xaxis[[test_id]][[2]] + log_scale <- "" + } + + # Plots the graph with GFLOPS on the Y-axis + if (metric_gflops) { + plot_graph(xdata=xdata, ydata=list(db$GFLOPS_1, db$GFLOPS_2), log_setting=log_scale, + xmin=min(xdata), xmax=max(xdata), + ymin=0, ymax=max(max(db$GFLOPS_1),max(db$GFLOPS_2)), + xtics=xtics, + xlabel=test_xlabels[[test_id]], ylabel="GFLOPS (higher is better)", + graph_title=paste(display_name, test_names[[test_id]], sep=" "), + multiple=50, experiment_names=library_names) + # Plots the graph with GB/s on the Y-axis + } else { + plot_graph(xdata=xdata, ydata=list(db$GBs_1, db$GBs_2), log_setting=log_scale, + xmin=min(xdata), xmax=max(xdata), + ymin=0, ymax=max(max(db$GBs_1),max(db$GBs_2)), + xtics=xtics, + xlabel=test_xlabels[[test_id]], ylabel="GB/s (higher is better)", + graph_title=paste(display_name, test_names[[test_id]], sep=" "), + multiple=10, experiment_names=library_names) + } + } +} + +# ================================================================================================== + +# Plots data +plot_graph <- function(xdata, ydata, log_setting, + xmin, xmax, ymin, ymax, + xtics, xlabel, ylabel, + graph_title, + multiple, experiment_names) { + + # Update the ymax to the next multiple of something + ymax <- multiple*ceiling(ymax/multiple) + + # Add kilo or mega to the x-labels + for (i in 1:length(xtics)) { + if (!is.na(as.numeric(xtics[i]))) { + if (as.numeric(xtics[i])%%mega == 0) { + xtics[i] <- paste(as.character(as.numeric(xtics[i])/mega), "M", sep="") + } else if (as.numeric(xtics[i])%%kilo == 0) { + xtics[i] <- paste(as.character(as.numeric(xtics[i])/kilo), "K", sep="") + } + } + } + + # Creates an initial graph with axis but without data + par(new=F) + plot(x=xmin:xmax, y=rep(1, length(xmin:xmax)), log=log_setting, + main="", xlab="", ylab="", + ylim=c(ymin, ymax), xlim=c(xmin, xmax), axes=F, "n") + axis(side=2, las=2) + axis(side=1, at=xdata, labels=xtics, las=2) + title(xlab=xlabel, line=-1) + title(ylab=ylabel, line=2) + title(graph_title, line=-2) + par(new=T) + + # Loops over all experiments + num_experiments <- length(ydata) + for (id in 1:num_experiments) { + + # Plots the data for this experiment + plot(x=xdata, y=ydata[[id]], log=log_setting, + col=colourset[id], pch=pchs[id], lty=1, lwd=1, cex=1, + xlab="", ylab="", ylim=c(ymin, ymax), xlim=c(xmin, xmax), + axes=F, "b", xpd=T) + par(new=T) + } + + # Add a legend + legend("bottomright", experiment_names, + lwd=1, ncol=1, col=colourset, pch=pchs, lty=1, cex=1, + bty="n", xpd=T) + + # Done + par(new=F) +} + +# ================================================================================================== diff --git a/test/performance/graphs/xaxpy.r b/test/performance/graphs/xaxpy.r new file mode 100644 index 00000000..187590aa --- /dev/null +++ b/test/performance/graphs/xaxpy.r @@ -0,0 +1,96 @@ + +# ================================================================================================== +# This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This +# project 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 implements the performance script for the Xaxpy routine +# +# ================================================================================================== + +# Includes the common functions +args <- commandArgs(trailingOnly = FALSE) +thisfile <- (normalizePath(sub("--file=", "", args[grep("--file=", args)]))) +source(file.path(dirname(thisfile), "common.r")) + +# ================================================================================================== + +# Settings +routine_name <- "xaxpy" +parameters <- c("-n","-incx","-incy", + "-num_steps","-step","-runs","-precision") +precision <- 32 + +# Sets the names of the test-cases +test_names <- list( + "multiples of 256K", + "multiples of 256K (+1)", + "around n=1M", + "around n=16M", + "strides (n=8M)", + "powers of 2" +) + +# Defines the test-cases +test_values <- list( + list(c(256*kilo, 1, 1, 16, 256*kilo, num_runs, precision)), + list(c(256*kilo+1, 1, 1, 16, 256*kilo, num_runs, precision)), + list(c(1*mega, 1, 1, 16, 1, num_runs, precision)), + list(c(16*mega, 1, 1, 16, 1, num_runs, precision)), + list( + c(8*mega, 1, 1, 1, 0, num_runs, precision), + c(8*mega, 2, 1, 1, 0, num_runs, precision), + c(8*mega, 4, 1, 1, 0, num_runs, precision), + c(8*mega, 8, 1, 1, 0, num_runs, precision), + c(8*mega, 1, 2, 1, 0, num_runs, precision), + c(8*mega, 1, 4, 1, 0, num_runs, precision), + c(8*mega, 1, 8, 1, 0, num_runs, precision), + c(8*mega, 2, 2, 1, 0, num_runs, precision), + c(8*mega, 4, 4, 1, 0, num_runs, precision), + c(8*mega, 8, 8, 1, 0, num_runs, precision) + ), + list( + c(32*kilo, 1, 1, 1, 0, num_runs, precision), + c(64*kilo, 1, 1, 1, 0, num_runs, precision), + c(128*kilo, 1, 1, 1, 0, num_runs, precision), + c(256*kilo, 1, 1, 1, 0, num_runs, precision), + c(512*kilo, 1, 1, 1, 0, num_runs, precision), + c(1*mega, 1, 1, 1, 0, num_runs, precision), + c(2*mega, 1, 1, 1, 0, num_runs, precision), + c(4*mega, 1, 1, 1, 0, num_runs, precision), + c(8*mega, 1, 1, 1, 0, num_runs, precision), + c(16*mega, 1, 1, 1, 0, num_runs, precision), + c(32*mega, 1, 1, 1, 0, num_runs, precision), + c(64*mega, 1, 1, 1, 0, num_runs, precision) + ) +) + +# Defines the x-labels corresponding to the test-cases +test_xlabels <- list( + "vector sizes (n)", + "vector sizes (n)", + "vector sizes (n)", + "vector sizes (n)", + "increments/strides for x and y", + "vector sizes (n)" +) + +# Defines the x-axis of the test-cases +test_xaxis <- list( + c("n", ""), + c("n", ""), + c("n", ""), + c("n", ""), + list(1:10, c("x1y1", "x2y1", "x4y1", "x8y1", "x1y2", "x1y4", "x1y8", "x2y2", "x4y4", "x8y8")), + c("n", "x") +) + +# ================================================================================================== + +# Start the script +main(routine_name=routine_name, precision=precision, test_names=test_names, test_values=test_values, + test_xlabels=test_xlabels, test_xaxis=test_xaxis, metric_gflops=FALSE) + +# ==================================================================================================
\ No newline at end of file diff --git a/test/performance/graphs/xgemm.r b/test/performance/graphs/xgemm.r new file mode 100755 index 00000000..22f63b77 --- /dev/null +++ b/test/performance/graphs/xgemm.r @@ -0,0 +1,94 @@ + +# ================================================================================================== +# This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This +# project 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 implements the performance script for the Xgemm routine +# +# ================================================================================================== + +# Includes the common functions +args <- commandArgs(trailingOnly = FALSE) +thisfile <- (normalizePath(sub("--file=", "", args[grep("--file=", args)]))) +source(file.path(dirname(thisfile), "common.r")) + +# ================================================================================================== + +# Settings +routine_name <- "xgemm" +parameters <- c("-m","-n","-k","-layout","-transA","-transB", + "-num_steps","-step","-runs","-precision") +precision <- 32 + +# Sets the names of the test-cases +test_names <- list( + "multiples of 128", + "multiples of 128 (+1)", + "around m=n=k=512", + "around m=n=k=2048", + "layouts and transposing (m=n=k=1024)", + "powers of 2" +) + +# Defines the test-cases +test_values <- list( + list(c(128, 128, 128, 0, 0, 0, 16, 128, num_runs, precision)), + list(c(129, 129, 129, 0, 0, 0, 16, 128, num_runs, precision)), + list(c(512, 512, 512, 0, 0, 0, 16, 1, num_runs, precision)), + list(c(2048, 2048, 2048, 0, 0, 0, 16, 1, num_runs, precision)), + list( + c(1024, 1024, 1024, 0, 0, 0, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 0, 0, 1, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 0, 1, 0, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 0, 1, 1, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 1, 0, 0, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 1, 0, 1, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 1, 1, 0, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 1, 1, 1, 1, 0, num_runs, precision) + ), + list( + c(8, 8, 8, 0, 0, 0, 1, 0, num_runs, precision), + c(16, 16, 16, 0, 0, 0, 1, 0, num_runs, precision), + c(32, 32, 32, 0, 0, 0, 1, 0, num_runs, precision), + c(64, 64, 64, 0, 0, 0, 1, 0, num_runs, precision), + c(128, 128, 128, 0, 0, 0, 1, 0, num_runs, precision), + c(256, 256, 256, 0, 0, 0, 1, 0, num_runs, precision), + c(512, 512, 512, 0, 0, 0, 1, 0, num_runs, precision), + c(1024, 1024, 1024, 0, 0, 0, 1, 0, num_runs, precision), + c(2048, 2048, 2048, 0, 0, 0, 1, 0, num_runs, precision), + c(4096, 4096, 4096, 0, 0, 0, 1, 0, num_runs, precision), + c(8192, 8192, 8192, 0, 0, 0, 1, 0, num_runs, precision) + ) +) + +# Defines the x-labels corresponding to the test-cases +test_xlabels <- list( + "matrix sizes (m=n=k)", + "matrix sizes (m=n=k)", + "matrix sizes (m=n=k)", + "matrix sizes (m=n=k)", + "layout (row/col), transA (n/y), transB (n/y)", + "matrix sizes (m=n=k)" +) + +# Defines the x-axis of the test-cases +test_xaxis <- list( + c("m", ""), + c("m", ""), + c("m", ""), + c("m", ""), + list(1:8, c("row,n,n", "row,n,y", "row,y,n", "row,y,y", + "col,n,n", "col,n,y", "col,y,n", "col,y,y")), + c("m", "x") +) + +# ================================================================================================== + +# Start the script +main(routine_name=routine_name, precision=precision, test_names=test_names, test_values=test_values, + test_xlabels=test_xlabels, test_xaxis=test_xaxis, metric_gflops=TRUE) + +# ==================================================================================================
\ No newline at end of file diff --git a/test/performance/graphs/xsymm.r b/test/performance/graphs/xsymm.r new file mode 100644 index 00000000..6493f52a --- /dev/null +++ b/test/performance/graphs/xsymm.r @@ -0,0 +1,94 @@ + +# ================================================================================================== +# This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This +# project 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 implements the performance script for the Xsymm routine +# +# ================================================================================================== + +# Includes the common functions +args <- commandArgs(trailingOnly = FALSE) +thisfile <- (normalizePath(sub("--file=", "", args[grep("--file=", args)]))) +source(file.path(dirname(thisfile), "common.r")) + +# ================================================================================================== + +# Settings +routine_name <- "xsymm" +parameters <- c("-m","-n","-layout","-triangle","-side", + "-num_steps","-step","-runs","-precision") +precision <- 32 + +# Sets the names of the test-cases +test_names <- list( + "multiples of 128", + "multiples of 128 (+1)", + "around m=n=512", + "around m=n=2048", + "layouts and triangle/side (m=n=1024)", + "powers of 2" +) + +# Defines the test-cases +test_values <- list( + list(c(128, 128, 0, 0, 0, 16, 128, num_runs, precision)), + list(c(129, 129, 0, 0, 0, 16, 128, num_runs, precision)), + list(c(512, 512, 0, 0, 0, 16, 1, num_runs, precision)), + list(c(2048, 2048, 0, 0, 0, 16, 1, num_runs, precision)), + list( + c(1024, 1024, 0, 0, 0, 1, 0, num_runs, precision), + c(1024, 1024, 0, 0, 1, 1, 0, num_runs, precision), + c(1024, 1024, 0, 1, 0, 1, 0, num_runs, precision), + c(1024, 1024, 0, 1, 1, 1, 0, num_runs, precision), + c(1024, 1024, 1, 0, 0, 1, 0, num_runs, precision), + c(1024, 1024, 1, 0, 1, 1, 0, num_runs, precision), + c(1024, 1024, 1, 1, 0, 1, 0, num_runs, precision), + c(1024, 1024, 1, 1, 1, 1, 0, num_runs, precision) + ), + list( + c(8, 8, 0, 0, 0, 1, 0, num_runs, precision), + c(16, 16, 0, 0, 0, 1, 0, num_runs, precision), + c(32, 32, 0, 0, 0, 1, 0, num_runs, precision), + c(64, 64, 0, 0, 0, 1, 0, num_runs, precision), + c(128, 128, 0, 0, 0, 1, 0, num_runs, precision), + c(256, 256, 0, 0, 0, 1, 0, num_runs, precision), + c(512, 512, 0, 0, 0, 1, 0, num_runs, precision), + c(1024, 1024, 0, 0, 0, 1, 0, num_runs, precision), + c(2048, 2048, 0, 0, 0, 1, 0, num_runs, precision), + c(4096, 4096, 0, 0, 0, 1, 0, num_runs, precision), + c(8192, 8192, 0, 0, 0, 1, 0, num_runs, precision) + ) +) + +# Defines the x-labels corresponding to the test-cases +test_xlabels <- list( + "matrix sizes (m=n)", + "matrix sizes (m=n)", + "matrix sizes (m=n)", + "matrix sizes (m=n)", + "layout (row/col), triangle (up/lo), side (l/r)", + "matrix sizes (m=n)" +) + +# Defines the x-axis of the test-cases +test_xaxis <- list( + c("m", ""), + c("m", ""), + c("m", ""), + c("m", ""), + list(1:8, c("row,up,l", "row,up,r", "row,lo,l", "row,lo,r", + "col,up,l", "col,up,r", "col,lo,l", "col,lo,r")), + c("m", "x") +) + +# ================================================================================================== + +# Start the script +main(routine_name=routine_name, precision=precision, test_names=test_names, test_values=test_values, + test_xlabels=test_xlabels, test_xaxis=test_xaxis, metric_gflops=TRUE) + +# ==================================================================================================
\ No newline at end of file diff --git a/test/performance/routines/xaxpy.cc b/test/performance/routines/xaxpy.cc new file mode 100644 index 00000000..23d76099 --- /dev/null +++ b/test/performance/routines/xaxpy.cc @@ -0,0 +1,97 @@ + +// ================================================================================================= +// 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 implements the Xaxpy command-line interface tester. +// +// ================================================================================================= + +#include <string> +#include <vector> +#include <exception> + +#include "wrapper_clblas.h" +#include "performance/client.h" + +namespace clblast { +// ================================================================================================= + +// The client, used for performance testing. It contains the function calls to CLBlast and to other +// libraries to compare against. +template <typename T> +void PerformanceXaxpy(const Arguments<T> &args, + const Buffer &x_vec, const Buffer &y_vec, + CommandQueue &queue) { + + // Creates the CLBlast lambda + auto clblast_lambda = [&args, &x_vec, &y_vec, &queue]() { + auto queue_plain = queue(); + auto event = cl_event{}; + auto status = Axpy(args.n, args.alpha, + x_vec(), args.x_offset, args.x_inc, + y_vec(), args.y_offset, args.y_inc, + &queue_plain, &event); + clWaitForEvents(1, &event); + if (status != StatusCode::kSuccess) { + throw std::runtime_error("CLBlast error: "+ToString(static_cast<int>(status))); + } + }; + + // Creates the clBLAS lambda (for comparison) + auto clblas_lambda = [&args, &x_vec, &y_vec, &queue]() { + auto queue_plain = queue(); + auto event = cl_event{}; + auto status = clblasXaxpy(args.n, args.alpha, + x_vec(), args.x_offset, args.x_inc, + y_vec(), args.y_offset, args.y_inc, + 1, &queue_plain, 0, nullptr, &event); + clWaitForEvents(1, &event); + if (status != CL_SUCCESS) { + throw std::runtime_error("clBLAS error: "+ToString(static_cast<int>(status))); + } + }; + + // Runs the routines and collect the timings + auto ms_clblast = TimedExecution(args.num_runs, clblast_lambda); + auto ms_clblas = TimedExecution(args.num_runs, clblas_lambda); + + // Prints the performance of both libraries + const auto flops = 2 * args.n; + const auto bytes = (3 * args.n) * sizeof(T); + const auto output_ints = std::vector<size_t>{args.n, args.x_inc, args.y_inc, + args.x_offset, args.y_offset}; + const auto output_strings = std::vector<std::string>{ToString(args.alpha)}; + PrintTableRow(output_ints, output_strings, args.no_abbrv, + ms_clblast, ms_clblas, flops, bytes); +} + +// ================================================================================================= + +// Main function which calls the common client code with the routine-specific function as argument. +void ClientXaxpy(int argc, char *argv[]) { + const auto o = std::vector<std::string>{kArgN, kArgXInc, kArgYInc, + kArgXOffset, kArgYOffset, kArgAlpha}; + switch(GetPrecision(argc, argv)) { + case Precision::kHalf: throw std::runtime_error("Unsupported precision mode"); + case Precision::kSingle: ClientXY<float>(argc, argv, PerformanceXaxpy<float>, o); break; + case Precision::kDouble: ClientXY<double>(argc, argv, PerformanceXaxpy<double>, o); break; + case Precision::kComplexSingle: ClientXY<float2>(argc, argv, PerformanceXaxpy<float2>, o); break; + case Precision::kComplexDouble: ClientXY<double2>(argc, argv, PerformanceXaxpy<double2>, o); break; + } +} + +// ================================================================================================= +} // namespace clblast + +// Main function (not within the clblast namespace) +int main(int argc, char *argv[]) { + clblast::ClientXaxpy(argc, argv); + return 0; +} + +// ================================================================================================= diff --git a/test/performance/routines/xgemm.cc b/test/performance/routines/xgemm.cc new file mode 100644 index 00000000..234e9fdb --- /dev/null +++ b/test/performance/routines/xgemm.cc @@ -0,0 +1,115 @@ + +// ================================================================================================= +// 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 implements the Xgemm command-line interface tester. +// +// ================================================================================================= + +#include <string> +#include <vector> +#include <exception> + +#include "wrapper_clblas.h" +#include "performance/client.h" + +namespace clblast { +// ================================================================================================= + +// The client, used for performance testing. It contains the function calls to CLBlast and to other +// libraries to compare against. +template <typename T> +void PerformanceXgemm(const Arguments<T> &args, + const Buffer &a_mat, const Buffer &b_mat, const Buffer &c_mat, + CommandQueue &queue) { + + // Creates the CLBlast lambda + auto clblast_lambda = [&args, &a_mat, &b_mat, &c_mat, &queue]() { + auto queue_plain = queue(); + auto event = cl_event{}; + auto status = Gemm(args.layout, args.a_transpose, args.b_transpose, + args.m, args.n, args.k, + args.alpha, + a_mat(), args.a_offset, args.a_ld, + b_mat(), args.b_offset, args.b_ld, + args.beta, + c_mat(), args.c_offset, args.c_ld, + &queue_plain, &event); + clWaitForEvents(1, &event); + if (status != StatusCode::kSuccess) { + throw std::runtime_error("CLBlast error: "+ToString(static_cast<int>(status))); + } + }; + + // Creates the clBLAS lambda (for comparison) + auto clblas_lambda = [&args, &a_mat, &b_mat, &c_mat, &queue]() { + auto queue_plain = queue(); + auto event = cl_event{}; + auto status = clblasXgemm(static_cast<clblasOrder>(args.layout), + static_cast<clblasTranspose>(args.a_transpose), + static_cast<clblasTranspose>(args.b_transpose), + args.m, args.n, args.k, + args.alpha, + a_mat(), args.a_offset, args.a_ld, + b_mat(), args.b_offset, args.b_ld, + args.beta, + c_mat(), args.c_offset, args.c_ld, + 1, &queue_plain, 0, nullptr, &event); + clWaitForEvents(1, &event); + if (status != CL_SUCCESS) { + throw std::runtime_error("clBLAS error: "+ToString(static_cast<int>(status))); + } + }; + + // Runs the routines and collect the timings + auto ms_clblast = TimedExecution(args.num_runs, clblast_lambda); + auto ms_clblas = TimedExecution(args.num_runs, clblas_lambda); + + // Prints the performance of both libraries + const auto flops = 2 * args.m * args.n * args.k; + const auto bytes = (args.m*args.k + args.k*args.n + args.m*args.n) * sizeof(T); + const auto output_ints = std::vector<size_t>{args.m, args.n, args.k, + static_cast<size_t>(args.layout), + static_cast<size_t>(args.a_transpose), + static_cast<size_t>(args.b_transpose), + args.a_ld, args.b_ld, args.c_ld, + args.a_offset, args.b_offset, args.c_offset}; + const auto output_strings = std::vector<std::string>{ToString(args.alpha), + ToString(args.beta)}; + PrintTableRow(output_ints, output_strings, args.no_abbrv, + ms_clblast, ms_clblas, flops, bytes); +} + +// ================================================================================================= + +// Main function which calls the common client code with the routine-specific function as argument. +void ClientXgemm(int argc, char *argv[]) { + const auto o = std::vector<std::string>{kArgM, kArgN, kArgK, kArgLayout, + kArgATransp, kArgBTransp, + kArgALeadDim, kArgBLeadDim, kArgCLeadDim, + kArgAOffset, kArgBOffset, kArgCOffset, + kArgAlpha, kArgBeta}; + switch(GetPrecision(argc, argv)) { + case Precision::kHalf: throw std::runtime_error("Unsupported precision mode"); + case Precision::kSingle: ClientABC<float>(argc, argv, PerformanceXgemm<float>, o); break; + case Precision::kDouble: ClientABC<double>(argc, argv, PerformanceXgemm<double>, o); break; + case Precision::kComplexSingle: throw std::runtime_error("Unsupported precision mode"); + case Precision::kComplexDouble: throw std::runtime_error("Unsupported precision mode"); + } +} + +// ================================================================================================= +} // namespace clblast + +// Main function (not within the clblast namespace) +int main(int argc, char *argv[]) { + clblast::ClientXgemm(argc, argv); + return 0; +} + +// ================================================================================================= diff --git a/test/performance/routines/xsymm.cc b/test/performance/routines/xsymm.cc new file mode 100644 index 00000000..13ad434a --- /dev/null +++ b/test/performance/routines/xsymm.cc @@ -0,0 +1,115 @@ + +// ================================================================================================= +// 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 implements the Xsymm command-line interface tester. +// +// ================================================================================================= + +#include <string> +#include <vector> +#include <exception> + +#include "wrapper_clblas.h" +#include "performance/client.h" + +namespace clblast { +// ================================================================================================= + +// The client, used for performance testing. It contains the function calls to CLBlast and to other +// libraries to compare against. +template <typename T> +void PerformanceXsymm(const Arguments<T> &args, + const Buffer &a_mat, const Buffer &b_mat, const Buffer &c_mat, + CommandQueue &queue) { + + // Creates the CLBlast lambda + auto clblast_lambda = [&args, &a_mat, &b_mat, &c_mat, &queue]() { + auto queue_plain = queue(); + auto event = cl_event{}; + auto status = Symm(args.layout, args.side, args.triangle, + args.m, args.n, + args.alpha, + a_mat(), args.a_offset, args.a_ld, + b_mat(), args.b_offset, args.b_ld, + args.beta, + c_mat(), args.c_offset, args.c_ld, + &queue_plain, &event); + clWaitForEvents(1, &event); + if (status != StatusCode::kSuccess) { + throw std::runtime_error("CLBlast error: "+ToString(static_cast<int>(status))); + } + }; + + // Creates the clBLAS lambda (for comparison) + auto clblas_lambda = [&args, &a_mat, &b_mat, &c_mat, &queue]() { + auto queue_plain = queue(); + auto event = cl_event{}; + auto status = clblasXsymm(static_cast<clblasOrder>(args.layout), + static_cast<clblasSide>(args.side), + static_cast<clblasUplo>(args.triangle), + args.m, args.n, + args.alpha, + a_mat(), args.a_offset, args.a_ld, + b_mat(), args.b_offset, args.b_ld, + args.beta, + c_mat(), args.c_offset, args.c_ld, + 1, &queue_plain, 0, nullptr, &event); + clWaitForEvents(1, &event); + if (status != CL_SUCCESS) { + throw std::runtime_error("clBLAS error: "+ToString(static_cast<int>(status))); + } + }; + + // Runs the routines and collect the timings + auto ms_clblast = TimedExecution(args.num_runs, clblast_lambda); + auto ms_clblas = TimedExecution(args.num_runs, clblas_lambda); + + // Prints the performance of both libraries + const auto flops = 2 * args.m * args.n * args.m; + const auto bytes = (args.m*args.m + args.m*args.n + args.m*args.n) * sizeof(T); + const auto output_ints = std::vector<size_t>{args.m, args.n, + static_cast<size_t>(args.layout), + static_cast<size_t>(args.triangle), + static_cast<size_t>(args.side), + args.a_ld, args.b_ld, args.c_ld, + args.a_offset, args.b_offset, args.c_offset}; + const auto output_strings = std::vector<std::string>{ToString(args.alpha), + ToString(args.beta)}; + PrintTableRow(output_ints, output_strings, args.no_abbrv, + ms_clblast, ms_clblas, flops, bytes); +} + +// ================================================================================================= + +// Main function which calls the common client code with the routine-specific function as argument. +void ClientXsymm(int argc, char *argv[]) { + const auto o = std::vector<std::string>{kArgM, kArgN, kArgLayout, + kArgTriangle, kArgSide, + kArgALeadDim, kArgBLeadDim, kArgCLeadDim, + kArgAOffset, kArgBOffset, kArgCOffset, + kArgAlpha, kArgBeta}; + switch(GetPrecision(argc, argv)) { + case Precision::kHalf: throw std::runtime_error("Unsupported precision mode"); + case Precision::kSingle: ClientABC<float>(argc, argv, PerformanceXsymm<float>, o); break; + case Precision::kDouble: ClientABC<double>(argc, argv, PerformanceXsymm<double>, o); break; + case Precision::kComplexSingle: throw std::runtime_error("Unsupported precision mode"); + case Precision::kComplexDouble: throw std::runtime_error("Unsupported precision mode"); + } +} + +// ================================================================================================= +} // namespace clblast + +// Main function (not within the clblast namespace) +int main(int argc, char *argv[]) { + clblast::ClientXsymm(argc, argv); + return 0; +} + +// ================================================================================================= |