This commit is contained in:
bronku 2025-11-17 19:39:10 +01:00
parent 1f6b998063
commit 3030f9bd98
6 changed files with 50 additions and 33 deletions

View file

@ -4,14 +4,18 @@
class Configuration {
public:
// I/O settings
std::string input_file = "1.in";
std::string output_file = "1.out";
std::string tmp_dir = "build/run";
bool generate_data = false;
bool evaluate_file = false;
int N = 100000; // number of records in a file
int n = 101; // number of buffers
int b = 10; // blocking factor
std::string tmp_directory = "run";
// Algorithm settings
size_t buffer_rows = 101;
size_t buffer_cols = 10;
// Additional modes
size_t generate_data = 0;
bool read_file = false;
Configuration(int argc, char** argv);
};

View file

@ -21,9 +21,9 @@ private:
public:
MergeSorter(size_t buffer_rows, size_t buffer_cols, const std::string& tmp_dir);
bool sort_file(const std::string& input_file, const std::string& output_file);
void sort_file(const std::string& input_file, const std::string& output_file);
size_t disk_reads() const;
size_t disk_writes() const;
size_t phases() const;
size_t disk_reads();
size_t disk_writes();
size_t phases();
};

View file

@ -24,10 +24,10 @@ generate: build/run/1.in
# actually should depend on build/main and build/run, but that will trigger it every recompile, and i don't need that
build/run/1.in:
$(TARGET) -g -o build/run/1.in
$(TARGET) -g 100000 -o build/run/1.in
run: $(TARGET) build/run/1.in
$(TARGET) -i build/run/1.in -d build/run/tmp
$(TARGET) -i build/run/1.in -d build/run/tmp -o build/run/1.out
run_alt: $(TARGET) build/run/1.in
$(TARGET) -i build/run/1.in -d build/run/tmp -n 11 -b 100

View file

@ -6,13 +6,13 @@ Configuration::Configuration(int argc, char** argv)
{
if (argc <= 1) {
std::cerr << "Please specify input arguments\n";
std::cerr << "Usage: " << argv[0] << " [-g] [-e] [-N count] [-i input] [-o output] [-d dir] [-n buffers] [-b block_size]\n";
std::cerr << "Usage: " << argv[0] << " [-g count] [-e] [-i input] [-o output] [-d dir] [-n buffers] [-b block_size]\n";
throw std::invalid_argument("No input arguments");
}
bool input_set = false;
int opt;
while ((opt = getopt(argc, argv, "i:d:o:geN:n:b:")) != -1) {
while ((opt = getopt(argc, argv, "i:d:o:g:en:b:")) != -1) {
switch (opt) {
case 'i':
input_file = optarg;
@ -22,22 +22,19 @@ Configuration::Configuration(int argc, char** argv)
output_file = optarg;
break;
case 'd':
tmp_dir = optarg;
tmp_directory = optarg;
break;
case 'g':
generate_data = true;
generate_data = std::stoi(optarg);
break;
case 'e':
evaluate_file = true;
break;
case 'N':
N = std::stoi(optarg);
read_file = true;
break;
case 'n':
n = std::stoi(optarg);
buffer_rows = std::stoi(optarg);
break;
case 'b':
b = std::stoi(optarg);
buffer_cols = std::stoi(optarg);
break;
case '?':
throw std::invalid_argument("Invalid command line argument");
@ -49,7 +46,7 @@ Configuration::Configuration(int argc, char** argv)
if (generate_data && input_set) {
throw std::invalid_argument("Cannot specify both -g and -i options");
}
if (generate_data && evaluate_file) {
if (generate_data && read_file) {
throw std::invalid_argument("Cannot specify both -g and -e options");
}
}

View file

@ -21,13 +21,13 @@ void generate_file(int N, const std::string& filename)
void read_and_evaluate(std::string filename)
{
FileReader input(filename);
while (true) {
for (size_t i = 0;; i++) {
auto rec = input.read();
if (!rec.has_value()) {
return;
}
std::cout << "[Evaluate: " << rec.value().evaluate() << "] " << rec.value() << "\n";
std::cout << "record " << i << " [value: " << rec.value().evaluate() << "] " << rec.value() << "\n";
}
}
@ -36,15 +36,18 @@ int main(int argc, char** argv)
Configuration opts(argc, argv);
if (opts.generate_data) {
generate_file(opts.N, opts.output_file);
generate_file(opts.generate_data, opts.output_file);
return 0;
}
if (opts.evaluate_file) {
if (opts.read_file) {
read_and_evaluate(opts.input_file);
return 0;
}
MergeSorter sorter(opts.b, opts.n, opts.tmp_dir);
MergeSorter sorter(opts.buffer_cols, opts.buffer_rows, opts.tmp_directory);
sorter.sort_file(opts.input_file, opts.output_file);
std::cout << "total reads: " << sorter.disk_reads() << '\n'
<< "total writes: " << sorter.disk_writes() << '\n'
<< "phases: " << sorter.phases() << "\n";
}

View file

@ -138,7 +138,7 @@ MergeSorter::MergeSorter(size_t buffer_rows, size_t buffer_cols, const std::stri
}
}
bool MergeSorter::sort_file(const std::string& input_file, const std::string& output_file)
void MergeSorter::sort_file(const std::string& input_file, const std::string& output_file)
{
std::string current_dir = tmp_dir_ + "/pass0/run_";
std::string next_dir = tmp_dir_ + "/pass1/run_";
@ -146,16 +146,29 @@ bool MergeSorter::sort_file(const std::string& input_file, const std::string& ou
run_count = create_initial_runs(input_file, current_dir);
phases_++;
std::cout << "created inital runs, disk reads: " << disk_reads_ << ", disk writes: " << disk_writes_ << '\n';
while (run_count > 1) {
run_count = merge_pass(current_dir, next_dir, run_count);
std::cout << "completed merge pass " << phases_ << ", disk reads: " << disk_reads_ << ", disk writes: " << disk_writes_ << '\n';
phases_++;
current_dir = next_dir;
next_dir = tmp_dir_ + "/pass" + std::to_string(phases_) + "/run_";
}
std::cout << output_file << '\n';
return true;
std::string final_run = current_dir + "0.dat";
std::filesystem::rename(final_run, output_file);
}
size_t MergeSorter::disk_reads()
{
return disk_reads_;
}
size_t MergeSorter::disk_writes()
{
return disk_writes_;
}
size_t MergeSorter::phases()
{
return phases_;
}