Files
paddlepaddle--paddle/test/cpp/pir/cinn/tile_config_performance_test.cc
T
2026-07-13 12:40:42 +08:00

777 lines
32 KiB
C++

// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <sys/stat.h>
#include <memory>
#include <sstream>
#include <fstream>
#include "paddle/cinn/hlir/dialect/operator/ir/op_dialect.h"
#include "paddle/cinn/ir/group_schedule/config/database.h"
#include "paddle/cinn/ir/group_schedule/config/file_database.h"
#include "paddle/cinn/ir/group_schedule/config/group_tile_config.h"
#include "paddle/cinn/ir/group_schedule/config/schedule_config_manager.h"
#include "paddle/cinn/ir/group_schedule/search/config_searcher.h"
#include "paddle/cinn/ir/group_schedule/search/measurer.h"
#include "paddle/cinn/utils/string.h"
#include "paddle/common/performance_statistician.h"
#include "paddle/fluid/pir/dialect/operator/ir/op_dialect.h"
#include "paddle/fluid/pir/dialect/operator/ir/pd_api.h"
#include "paddle/fluid/pir/dialect/operator/ir/pd_op.h"
#include "paddle/pir/include/core/builtin_type.h"
#include "paddle/pir/include/core/ir_context.h"
#include "paddle/pir/include/core/program.h"
PD_DECLARE_string(tile_config_policy);
PD_DECLARE_string(cinn_tile_config_filename_label);
COMMON_DECLARE_bool(print_ir);
PD_DECLARE_bool(cinn_measure_kernel_time);
PHI_DECLARE_bool(enable_cinn_compile_cache);
#define MKDIR(path) mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
struct PerfTestConfig {
int InnerTestNum;
int OuterTestNum;
int MaxTestNum;
float EarlyStopThreshold;
PerfTestConfig()
: InnerTestNum(1),
OuterTestNum(3),
MaxTestNum(3),
EarlyStopThreshold(1.2) {}
PerfTestConfig(int inner_num, int outer_num, int max_num, float earlystop)
: InnerTestNum(inner_num),
OuterTestNum(outer_num),
MaxTestNum(max_num),
EarlyStopThreshold(earlystop) {}
};
std::string GenCSVFilePath(const cinn::common::Target target,
const cinn::ir::IterSpaceType &iter_space_type) {
std::string dirname = "";
std::string filename = "";
for (auto i : iter_space_type) {
dirname += i.first;
dirname += "_";
filename += i.first + i.second;
filename += "_";
}
const std::string kDirSuffix = "_EREBE";
dirname = dirname.substr(0, dirname.size() - 1) + kDirSuffix;
filename = filename.substr(0, filename.size() - 1);
auto checkexist = [](std::string test_path) {
bool path_exists = false;
struct stat statbuf;
if (stat(test_path.c_str(), &statbuf) != -1) {
if (S_ISDIR(statbuf.st_mode)) {
path_exists = true;
}
}
if (!path_exists) {
PADDLE_ENFORCE_NE(MKDIR(test_path.c_str()),
-1,
::common::errors::PreconditionNotMet(
"Can not create directory: %s, Make sure you "
"have permission to write",
test_path));
}
};
std::string root_path = FLAGS_cinn_tile_config_filename_label;
if (root_path == "") {
const std::string kTestFileDir = "./tile_file_test/";
root_path = kTestFileDir;
}
std::string target_str = target.arch_str() + "_" + target.device_name_str();
checkexist(root_path);
checkexist(root_path + target_str);
checkexist(root_path + target_str + "/" + dirname);
VLOG(3) << "Dump_path is " << root_path + dirname + "/" + filename + ".csv";
return root_path + target_str + "/" + dirname + "/" + filename + ".csv";
}
void WriteBucketInfo(
std::ofstream &os,
const std::vector<std::pair<std::string, std::string>> &iter_space_type,
const cinn::ir::BucketInfo &bucket_info) {
std::stringstream ss;
ss << " { ";
for (int i = 0; i < iter_space_type.size(); ++i) {
ss << iter_space_type[i].first << "_" << iter_space_type[i].second << ": "
<< bucket_info.space[i].lower_bound << "-"
<< bucket_info.space[i].upper_bound << " ";
}
ss << "} ";
os << ss.str() << " \t ";
}
// reduce_sum
std::shared_ptr<::pir::Program> BuildReduceSumProgram(int spatial_size,
int reduce_size) {
::pir::IrContext *ctx = ::pir::IrContext::Instance();
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
auto program = std::make_shared<::pir::Program>(ctx);
::pir::Builder builder = ::pir::Builder(ctx, program->block());
const std::vector<int64_t> shape = {spatial_size, reduce_size};
auto x = builder
.Build<paddle::dialect::DataOp>(
"x", shape, phi::DataType::FLOAT32, phi::GPUPlace())
.result(0);
auto out = builder
.Build<paddle::dialect::SumOp>(
x, std::vector<int64_t>{-1}, phi::DataType::FLOAT32, true)
.result(0);
builder.Build<paddle::dialect::FetchOp>(out, "out", 0);
return program;
}
// layerNorm
std::shared_ptr<::pir::Program> BuildLayerNormProgram(int spatial_size,
int reduce_size) {
::pir::IrContext *ctx = ::pir::IrContext::Instance();
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
auto program = std::make_shared<::pir::Program>(ctx);
::pir::Builder builder = ::pir::Builder(ctx, program->block());
const std::vector<int64_t> shape = {spatial_size, reduce_size};
auto x = builder
.Build<paddle::dialect::DataOp>(
"x", shape, phi::DataType::FLOAT32, phi::GPUPlace())
.result(0);
auto sum_val =
builder
.Build<paddle::dialect::SumOp>(
x, std::vector<int64_t>{-1}, phi::DataType::FLOAT32, true)
.result(0);
auto divide_num =
builder
.Build<paddle::dialect::FullOp>(
std::vector<int64_t>({1}), 1024, phi::DataType::FLOAT32)
.out();
auto mean_val =
builder.Build<paddle::dialect::DivideOp>(sum_val, divide_num).result(0);
auto sub_num =
builder.Build<paddle::dialect::SubtractOp>(x, mean_val).result(0);
auto pow_val = builder.Build<paddle::dialect::PowOp>(x, 2.0).result(0);
auto pow_sum =
builder
.Build<paddle::dialect::SumOp>(
pow_val, std::vector<int64_t>{-1}, phi::DataType::FLOAT32, true)
.result(0);
auto variance_val =
builder.Build<paddle::dialect::DivideOp>(pow_sum, divide_num).result(0);
auto add_num =
builder
.Build<paddle::dialect::FullOp>(
std::vector<int64_t>({1}), 1e-6, phi::DataType::FLOAT32)
.out();
auto add_val =
builder.Build<paddle::dialect::AddOp>(variance_val, add_num).result(0);
auto rsqrt_val = builder.Build<paddle::dialect::RsqrtOp>(add_val).result(0);
auto out =
builder.Build<paddle::dialect::MultiplyOp>(rsqrt_val, sub_num).result(0);
builder.Build<paddle::dialect::FetchOp>(out, "out", 0);
return program;
}
// softmax
std::shared_ptr<::pir::Program> BuildSoftmaxProgram(int spatial_size,
int reduce_size) {
::pir::IrContext *ctx = ::pir::IrContext::Instance();
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
auto program = std::make_shared<::pir::Program>(ctx);
::pir::Builder builder = ::pir::Builder(ctx, program->block());
const std::vector<int64_t> shape = {spatial_size, reduce_size};
auto x = builder
.Build<paddle::dialect::DataOp>(
"x", shape, phi::DataType::FLOAT32, phi::GPUPlace())
.result(0);
auto max_num =
builder.Build<paddle::dialect::MaxOp>(x, std::vector<int64_t>{-1}, true)
.result(0);
auto sub_num =
builder.Build<paddle::dialect::SubtractOp>(x, max_num).result(0);
auto exp_num = builder.Build<paddle::dialect::ExpOp>(sub_num).result(0);
auto exp_sum =
builder
.Build<paddle::dialect::SumOp>(
exp_num, std::vector<int64_t>{-1}, phi::DataType::FLOAT32, true)
.result(0);
auto out =
builder.Build<paddle::dialect::DivideOp>(exp_num, exp_sum).result(0);
builder.Build<paddle::dialect::FetchOp>(out, "out", 0);
return program;
}
// RMSNorm
std::shared_ptr<::pir::Program> BuildRMSNormProgram(int spatial_size,
int reduce_size) {
::pir::IrContext *ctx = ::pir::IrContext::Instance();
ctx->GetOrRegisterDialect<paddle::dialect::OperatorDialect>();
auto program = std::make_shared<::pir::Program>(ctx);
::pir::Builder builder = ::pir::Builder(ctx, program->block());
const std::vector<int64_t> shape = {spatial_size, reduce_size};
auto x = builder
.Build<paddle::dialect::DataOp>(
"x", shape, phi::DataType::FLOAT32, phi::GPUPlace())
.result(0);
auto pow_val = builder.Build<paddle::dialect::PowOp>(x, 2.0).result(0);
auto sum_val =
builder
.Build<paddle::dialect::SumOp>(
pow_val, std::vector<int64_t>{-1}, phi::DataType::FLOAT32, true)
.result(0);
auto divide_num =
builder
.Build<paddle::dialect::FullOp>(
std::vector<int64_t>({1}), reduce_size, phi::DataType::FLOAT32)
.out();
auto div_val =
builder.Build<paddle::dialect::DivideOp>(sum_val, divide_num).result(0);
auto add_num =
builder
.Build<paddle::dialect::FullOp>(
std::vector<int64_t>({1}), 1e-6, phi::DataType::FLOAT32)
.out();
auto add_val =
builder.Build<paddle::dialect::AddOp>(div_val, add_num).result(0);
auto rsqrt_val = builder.Build<paddle::dialect::RsqrtOp>(add_val).result(0);
auto out = builder.Build<paddle::dialect::MultiplyOp>(rsqrt_val, x).result(0);
builder.Build<paddle::dialect::FetchOp>(out, "out", 0);
return program;
}
// Build test program for spatial reduce.
std::shared_ptr<::pir::Program> BuildSpatialReduceProgram(int spatial_size,
int reduce_size) {
std::shared_ptr<::pir::Program> program;
program = BuildSoftmaxProgram(spatial_size, reduce_size);
return program;
}
// Get the tile size configuration for the given dimension lower bound
// dynamically.
int get_tile_size_config_in_small_area(int dimension_lower) {
if (dimension_lower <= 2) {
return 126;
} else if (dimension_lower <= 128) {
return 384;
} else if (dimension_lower <= 512) {
return 512;
} else if (dimension_lower <= 1024) {
return 1024;
} else if (dimension_lower <= 2048) {
return 2048;
} else {
PADDLE_THROW(phi::errors::InvalidArgument(
"dimension_lower (%d) exceeds the supported range (<=2048).",
dimension_lower));
}
}
int get_tile_size_config_in_large_area(int dimension_lower) {
if (dimension_lower <= 2) {
return 510;
} else if (dimension_lower <= 512) {
return 512;
} else if (dimension_lower <= 4096) {
return 4096;
} else if (dimension_lower <= 8192) {
return 8192;
} else if (dimension_lower <= 16384) {
return 16384;
} else {
PADDLE_THROW(phi::errors::InvalidArgument(
"dimension_lower (%d) exceeds the supported range (<=16384).",
dimension_lower));
}
}
std::shared_ptr<::pir::Program> BuildProgram(bool is_spatial_dynamic,
bool is_reduce_dynamic,
int s_dimension_lower,
int r_dimension_lower) {
std::shared_ptr<::pir::Program> program;
if (!is_spatial_dynamic && !is_reduce_dynamic) {
program = BuildSpatialReduceProgram(s_dimension_lower, r_dimension_lower);
} else if (is_spatial_dynamic && !is_reduce_dynamic) {
program = BuildSpatialReduceProgram(-1, r_dimension_lower);
} else if (!is_spatial_dynamic && is_reduce_dynamic) {
program = BuildSpatialReduceProgram(s_dimension_lower, -1);
} else {
program = BuildSpatialReduceProgram(-1, -1);
}
return program;
}
cinn::ir::BucketInfo CreateBucket(int s_dimension_lower,
int spatial_tile_width,
int r_dimension_lower,
int reduce_tile_width,
bool is_spatial_dynamic,
bool is_reduce_dynamic) {
cinn::ir::BucketInfo bucket_info;
bucket_info.space.push_back(cinn::ir::BucketInfo::Dimension{
s_dimension_lower,
s_dimension_lower + spatial_tile_width - 1,
"S",
/* is_dynamic = */ is_spatial_dynamic});
bucket_info.space.push_back(
cinn::ir::BucketInfo::Dimension{r_dimension_lower,
r_dimension_lower + reduce_tile_width - 1,
"R",
/* is_dynamic = */ is_reduce_dynamic});
return bucket_info;
}
cinn::ir::search::CandidateType GetCandidate(
const cinn::ir::TileConfigMap &best_tile_config_map,
int s_dimension_lower,
int spatial_tile_width,
int r_dimension_lower,
int reduce_tile_width) {
cinn::ir::search::CandidateType best_candidate;
for (auto &it : best_tile_config_map) {
auto s_flag = false, r_flag = false;
auto dims = it.first.space.size();
// SR type support only
if (dims == 2) {
if (it.first.space[0].lower_bound <= s_dimension_lower &&
it.first.space[0].upper_bound >=
s_dimension_lower + spatial_tile_width - 1) {
s_flag = true;
} else if (it.first.space[0].lower_bound == 4096 &&
s_dimension_lower == 4096) {
s_flag = true;
}
if (it.first.space[1].lower_bound <= r_dimension_lower &&
it.first.space[1].upper_bound >=
r_dimension_lower + reduce_tile_width - 1) {
r_flag = true;
} else if (it.first.space[1].lower_bound == 4096 &&
r_dimension_lower == 4096) {
r_flag = true;
}
} else {
PADDLE_THROW(::common::errors::Unavailable("Now just support SR type."));
}
if (s_flag == true && r_flag == true) {
best_candidate = {it.second.warp_num,
it.second.tree_reduce_num,
it.second.spatial_inner_num};
break;
}
}
if (best_candidate.empty()) {
PADDLE_THROW(
::common::errors::Unavailable("Not found the best candidate."));
}
return best_candidate;
}
void TestWindowPerformance(
std::ofstream &os,
const PerfTestConfig &perf_test_config,
const int graph_num,
const int s_dimension_lower,
const int spatial_tile_width,
const int r_dimension_lower,
const int reduce_tile_width,
const int is_spatial_dynamic,
const int is_reduce_dynamic,
const double s_weight,
const double r_weight,
const double sampling_prob,
const int kMaxSamplingTimes,
const int kRepeats,
const cinn::ir::TileConfigMap &best_tile_config_map,
const std::vector<std::pair<std::string, std::string>> &iter_space_type) {
std::vector<double> s_weights =
std::vector<double>(spatial_tile_width, s_weight);
std::vector<double> r_weights =
std::vector<double>(reduce_tile_width, r_weight);
LOG(INFO) << "spatial tile dimension lower bound = " << s_dimension_lower
<< ", reduce tile dimension lower bound = " << r_dimension_lower
<< std::endl;
// Construct pir::Program.
std::shared_ptr<::pir::Program> program;
program = BuildProgram(is_spatial_dynamic,
is_reduce_dynamic,
s_dimension_lower,
r_dimension_lower);
// Construct iter space and objective function.
cinn::ir::BucketInfo bucket_info = CreateBucket(s_dimension_lower,
spatial_tile_width,
r_dimension_lower,
reduce_tile_width,
is_spatial_dynamic,
is_reduce_dynamic);
std::unique_ptr<cinn::ir::search::BaseObjectiveFunc> obj_func =
std::make_unique<cinn::ir::search::WeightedSamplingTrailObjectiveFunc>(
program.get(),
bucket_info,
sampling_prob,
kMaxSamplingTimes,
kRepeats,
std::vector<std::vector<double>>{s_weights, r_weights});
cinn::ir::search::CandidateType best_candidate =
GetCandidate(best_tile_config_map,
s_dimension_lower,
spatial_tile_width,
r_dimension_lower,
reduce_tile_width);
// Write current bucket info to csv file.
WriteBucketInfo(os, iter_space_type, bucket_info);
int InnerTestNum = perf_test_config.InnerTestNum;
int OuterTestNum = perf_test_config.OuterTestNum;
int MaxTestNum = perf_test_config.MaxTestNum;
float EarlyStopThreshold = perf_test_config.EarlyStopThreshold;
cinn::ir::search::ScoreType record_baseline_score;
cinn::ir::search::ScoreType record_best_score;
double record_best_variance = 0;
// start test loop
for (int current_test_num = 0; current_test_num < MaxTestNum;
++current_test_num) {
std::vector<cinn::ir::search::ScoreType> vec_best;
std::vector<cinn::ir::search::ScoreType> vec_baseline;
// start outer measure loop
for (int i = 0; i < OuterTestNum; ++i) {
cinn::ir::search::CandidateType default_candidate;
std::vector<cinn::ir::search::ScoreType> vec_best_score;
std::vector<cinn::ir::search::ScoreType> vec_baseline_score;
// start inner measure loop
for (int i = 0; i < InnerTestNum; i++) {
FLAGS_tile_config_policy = "default";
cinn::ir::search::ScoreType temp_baseline_score =
(*obj_func)(default_candidate);
FLAGS_tile_config_policy = "search";
cinn::ir::search::ScoreType temp_best_score =
(*obj_func)(best_candidate);
vec_best_score.push_back(temp_best_score);
vec_baseline_score.push_back(temp_baseline_score);
}
float best_total_time =
std::accumulate(vec_best_score.begin(), vec_best_score.end(), 0.0);
float baseline_total_time = std::accumulate(
vec_baseline_score.begin(), vec_baseline_score.end(), 0.0);
float best_avg_time = best_total_time / InnerTestNum;
float baseline_avg_time = baseline_total_time / InnerTestNum;
vec_best.push_back(best_avg_time);
vec_baseline.push_back(baseline_avg_time);
}
cinn::ir::search::ScoreType best_mean =
std::accumulate(vec_best.begin(), vec_best.end(), 0.0) / OuterTestNum;
cinn::ir::search::ScoreType baseline_mean =
std::accumulate(vec_baseline.begin(), vec_baseline.end(), 0.0) /
OuterTestNum;
// Compute variance of OuterTestNum times of outer measure in each test
double best_variance = 0.0;
double baseline_variance = 0.0;
for (int i = 0; i < OuterTestNum; i++) {
best_variance = best_variance + pow(vec_best[i] - best_mean, 2);
baseline_variance =
baseline_variance + pow(vec_baseline[i] - baseline_mean, 2);
}
best_variance = pow(best_variance / OuterTestNum, 0.5);
baseline_variance = pow(baseline_variance / OuterTestNum, 0.5);
// Early stop when current best_variance smaller than EarlyStopThreshold
if ((best_variance < EarlyStopThreshold) &&
(baseline_variance < EarlyStopThreshold)) {
record_baseline_score = baseline_mean;
record_best_score = best_mean;
record_best_variance = best_variance + baseline_variance;
break;
} else {
if (record_best_variance == 0) {
record_best_variance = best_variance + baseline_variance;
record_baseline_score = baseline_mean;
record_best_score = best_mean;
} else if ((best_variance + baseline_variance) < record_best_variance) {
record_best_variance = best_variance + baseline_variance;
record_baseline_score = baseline_mean;
record_best_score = best_mean;
}
}
} // end of test_num loop
cinn::ir::search::ScoreType optim_percentage =
(1 / (record_best_score)-1 / record_baseline_score) *
record_baseline_score;
LOG(INFO) << "Best score: " << record_best_score / graph_num;
LOG(INFO) << "Baseline score: " << record_baseline_score / graph_num;
LOG(INFO) << "variance: " << (record_best_variance / 2);
LOG(INFO) << "optim percentage: " << optim_percentage;
LOG(INFO) << "Best candidate: " << best_candidate[0] << " "
<< best_candidate[1] << " " << best_candidate[2];
// Write measure results to csv file
os << std::setprecision(3) << " " << record_baseline_score / graph_num
<< " \t " << record_best_score / graph_num << " \t " << optim_percentage
<< "\n";
}
void TestPerformanceForTileConfig(int spatial_left_bound,
int spatial_right_bound,
int reduce_left_bound,
int reduce_right_bound,
bool is_spatial_dynamic,
bool is_reduce_dynamic,
bool test_single_large) {
FLAGS_enable_cinn_compile_cache = false;
FLAGS_cinn_measure_kernel_time = true;
// set tile_file path to test path when user use default setting
std::string root_path = FLAGS_cinn_tile_config_filename_label;
if (root_path == "") {
const std::string kTestFileDir = "./tile_file_test/";
FLAGS_cinn_tile_config_filename_label = kTestFileDir;
}
constexpr int kThreadsPerWarp = 32;
constexpr int kMaxThreadsPerBlock = 1024;
// now each has the same weight
constexpr double s_w = 0.05;
constexpr double r_w = 0.05;
constexpr double sampling_prob = 1.0;
constexpr int kMaxSamplingTimes = 360;
constexpr int kRepeats = 5;
constexpr int kInnerTestNum = 1;
constexpr int kOuterTestNum = 3;
constexpr int kMaxTestNum = 1;
constexpr float kEarlyStopThreshold = 1.2;
// number of nodes in cudaGraph for test, which is defined in
// performance_statistician.h as graph_nodes_num_. This parameter is set to
// make measure results corresponding to one launch for better readability
constexpr int kGraphNum = 25;
// Define the initial grid size for the spatial and reduction dimensions
int spatial_tile_config = 0, reduce_tile_config = 0;
int spatial_tile_width = 0, reduce_tile_width = 0;
// Define weight for each dimension
double s_weight = (is_spatial_dynamic ? s_w : 1.0);
double r_weight = (is_reduce_dynamic ? r_w : 1.0);
auto s_dimension_type = "S";
auto r_dimension_type = "R";
// Define the performance test configuration.
PerfTestConfig perf_test_config = {
kInnerTestNum, kOuterTestNum, kMaxTestNum, kEarlyStopThreshold};
// Get best configuration from json by file database.
std::vector<std::pair<std::string, std::string>> iter_space_type = {
std::make_pair(s_dimension_type,
is_spatial_dynamic == true ? "dynamic" : "static"),
std::make_pair(r_dimension_type,
is_reduce_dynamic == true ? "dynamic" : "static")};
cinn::ir::FileTileConfigDatabase file_database;
cinn::ir::TileConfigMap best_tile_config_map =
file_database.GetConfigs(cinn::common::DefaultTarget(), iter_space_type);
// build csv file
std::string dump_path =
GenCSVFilePath(cinn::common::DefaultTarget(), iter_space_type);
std::ofstream os(dump_path, std::ofstream::app);
PADDLE_ENFORCE_EQ(os.good(),
true,
::common::errors::InvalidArgument(
"Cannot open the file to write: %s", dump_path));
// run performance test for each data grid
for (int s_dimension_lower = spatial_left_bound;
s_dimension_lower < spatial_right_bound ||
s_dimension_lower == spatial_right_bound &&
spatial_left_bound == spatial_right_bound;
s_dimension_lower += spatial_tile_config) {
// adjust the tile size for the spatial dimension dymaically
spatial_tile_config = get_tile_size_config_in_small_area(s_dimension_lower);
spatial_tile_width = (is_spatial_dynamic ? spatial_tile_config : 1);
for (int r_dimension_lower = reduce_left_bound;
r_dimension_lower < reduce_right_bound ||
r_dimension_lower == reduce_right_bound &&
reduce_left_bound == reduce_right_bound;
r_dimension_lower += reduce_tile_config) {
// adjust the tile size for the reduce dimension dymaically
reduce_tile_config =
get_tile_size_config_in_small_area(r_dimension_lower);
reduce_tile_width = (is_reduce_dynamic ? reduce_tile_config : 1);
TestWindowPerformance(os,
perf_test_config,
kGraphNum,
s_dimension_lower,
spatial_tile_width,
r_dimension_lower,
reduce_tile_width,
is_spatial_dynamic,
is_reduce_dynamic,
s_weight,
r_weight,
sampling_prob,
kMaxSamplingTimes,
kRepeats,
best_tile_config_map,
iter_space_type);
} // end of r_dimension_lower loop
} // end of s_dimension_lower loop
if (test_single_large) {
// (II) Test in the single large areas,
// i.e., S:[4096-32768]*R:[2-1024], S:[2-1024]*R:[4096-32768]
for (int s_dimension_lower = 2; s_dimension_lower < 1024;
s_dimension_lower += spatial_tile_config) {
// adjust the tile size for the spatial dimension dynamically
spatial_tile_config =
get_tile_size_config_in_large_area(s_dimension_lower);
spatial_tile_width = (is_spatial_dynamic ? spatial_tile_config : 1);
for (int r_dimension_lower = 4096; r_dimension_lower < 32768;
r_dimension_lower += reduce_tile_config) {
// adjust the tile size for the reduce dimension dymaically
reduce_tile_config =
get_tile_size_config_in_large_area(r_dimension_lower);
reduce_tile_width = (is_reduce_dynamic ? reduce_tile_config : 1);
TestWindowPerformance(os,
perf_test_config,
kGraphNum,
s_dimension_lower,
spatial_tile_width,
r_dimension_lower,
reduce_tile_width,
is_spatial_dynamic,
is_reduce_dynamic,
s_weight,
r_weight,
sampling_prob,
kMaxSamplingTimes,
kRepeats,
best_tile_config_map,
iter_space_type);
}
}
for (int s_dimension_lower = 4096; s_dimension_lower < 32768;
s_dimension_lower += spatial_tile_config) {
// adjust the tile size for the spatial dimension dymaically
spatial_tile_config =
get_tile_size_config_in_large_area(s_dimension_lower);
spatial_tile_width = (is_spatial_dynamic ? spatial_tile_config : 1);
for (int r_dimension_lower = 2; r_dimension_lower < 1024;
r_dimension_lower += reduce_tile_config) {
// adjust the tile size for the reduce dimension dymaically
reduce_tile_config =
get_tile_size_config_in_large_area(r_dimension_lower);
reduce_tile_width = (is_reduce_dynamic ? reduce_tile_config : 1);
// Run performance test and write measure results to csv file.
TestWindowPerformance(os,
perf_test_config,
kGraphNum,
s_dimension_lower,
spatial_tile_width,
r_dimension_lower,
reduce_tile_width,
is_spatial_dynamic,
is_reduce_dynamic,
s_weight,
r_weight,
sampling_prob,
kMaxSamplingTimes,
kRepeats,
best_tile_config_map,
iter_space_type);
}
}
}
os.close();
}
/**
* @brief Test case for the ConfigSearcher.
*
* This test case performs a perormance test for the best configuration derived
* from the ConfigSearcher. It iterates over different spatial and reduce tile
* sizes and constructs a pir::Program. The objective function used for the
* search is a WeightedSamplingTrailObjectiveFunc. The performance results are
* written into a CSV file, including the default score and the best candidate
* score.
*/
TEST(ConfigSearcher, TestPerfDynamicDynamic) {
constexpr int spatial_left_bound = 2; // for full test, set it to 2
constexpr int spatial_right_bound = 2; // for full test, set it to 4096
constexpr int reduce_left_bound = 2; // for full test, set it to 2
constexpr int reduce_right_bound = 2; // for full test, set it to 4096
constexpr bool is_spatial_dynamic = true;
constexpr bool is_reduce_dynamic = true;
bool test_single_large = false; // To test single large area, set it to true
TestPerformanceForTileConfig(spatial_left_bound,
spatial_right_bound,
reduce_left_bound,
reduce_right_bound,
is_spatial_dynamic,
is_reduce_dynamic,
test_single_large);
}
TEST(ConfigSearcher, TestPerfStaticDynamic) {
constexpr int spatial_left_bound = 2; // for full test, set it to 2
constexpr int spatial_right_bound = 2; // for full test, set it to 4096
constexpr int reduce_left_bound = 2; // for full test, set it to 2
constexpr int reduce_right_bound = 2; // for full test, set it to 4096
constexpr bool is_spatial_dynamic = false;
constexpr bool is_reduce_dynamic = true;
bool test_single_large = false; // To test single large area, set it to true
TestPerformanceForTileConfig(spatial_left_bound,
spatial_right_bound,
reduce_left_bound,
reduce_right_bound,
is_spatial_dynamic,
is_reduce_dynamic,
test_single_large);
}
TEST(ConfigSearcher, TestPerfDynamicStatic) {
constexpr int spatial_left_bound = 2; // for full test, set it to 2
constexpr int spatial_right_bound = 2; // for full test, set it to 4096
constexpr int reduce_left_bound = 2; // for full test, set it to 2
constexpr int reduce_right_bound = 2; // for full test, set it to 4096
constexpr bool is_spatial_dynamic = true;
constexpr bool is_reduce_dynamic = false;
bool test_single_large = false; // To test single large area, set it to true
TestPerformanceForTileConfig(spatial_left_bound,
spatial_right_bound,
reduce_left_bound,
reduce_right_bound,
is_spatial_dynamic,
is_reduce_dynamic,
test_single_large);
}