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

View file

@ -21,9 +21,9 @@ private:
public: public:
MergeSorter(size_t buffer_rows, size_t buffer_cols, const std::string& tmp_dir); 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_reads();
size_t disk_writes() const; size_t disk_writes();
size_t phases() const; 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 # 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: 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 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 run_alt: $(TARGET) build/run/1.in
$(TARGET) -i build/run/1.in -d build/run/tmp -n 11 -b 100 $(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) { if (argc <= 1) {
std::cerr << "Please specify input arguments\n"; 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"); throw std::invalid_argument("No input arguments");
} }
bool input_set = false; bool input_set = false;
int opt; 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) { switch (opt) {
case 'i': case 'i':
input_file = optarg; input_file = optarg;
@ -22,22 +22,19 @@ Configuration::Configuration(int argc, char** argv)
output_file = optarg; output_file = optarg;
break; break;
case 'd': case 'd':
tmp_dir = optarg; tmp_directory = optarg;
break; break;
case 'g': case 'g':
generate_data = true; generate_data = std::stoi(optarg);
break; break;
case 'e': case 'e':
evaluate_file = true; read_file = true;
break;
case 'N':
N = std::stoi(optarg);
break; break;
case 'n': case 'n':
n = std::stoi(optarg); buffer_rows = std::stoi(optarg);
break; break;
case 'b': case 'b':
b = std::stoi(optarg); buffer_cols = std::stoi(optarg);
break; break;
case '?': case '?':
throw std::invalid_argument("Invalid command line argument"); throw std::invalid_argument("Invalid command line argument");
@ -49,7 +46,7 @@ Configuration::Configuration(int argc, char** argv)
if (generate_data && input_set) { if (generate_data && input_set) {
throw std::invalid_argument("Cannot specify both -g and -i options"); 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"); 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) void read_and_evaluate(std::string filename)
{ {
FileReader input(filename); FileReader input(filename);
while (true) { for (size_t i = 0;; i++) {
auto rec = input.read(); auto rec = input.read();
if (!rec.has_value()) { if (!rec.has_value()) {
return; 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); Configuration opts(argc, argv);
if (opts.generate_data) { if (opts.generate_data) {
generate_file(opts.N, opts.output_file); generate_file(opts.generate_data, opts.output_file);
return 0; return 0;
} }
if (opts.evaluate_file) { if (opts.read_file) {
read_and_evaluate(opts.input_file); read_and_evaluate(opts.input_file);
return 0; 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); 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 current_dir = tmp_dir_ + "/pass0/run_";
std::string next_dir = tmp_dir_ + "/pass1/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); run_count = create_initial_runs(input_file, current_dir);
phases_++; phases_++;
std::cout << "created inital runs, disk reads: " << disk_reads_ << ", disk writes: " << disk_writes_ << '\n';
while (run_count > 1) { while (run_count > 1) {
run_count = merge_pass(current_dir, next_dir, run_count); 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_++; phases_++;
current_dir = next_dir; current_dir = next_dir;
next_dir = tmp_dir_ + "/pass" + std::to_string(phases_) + "/run_"; next_dir = tmp_dir_ + "/pass" + std::to_string(phases_) + "/run_";
} }
std::cout << output_file << '\n'; std::string final_run = current_dir + "0.dat";
return true; 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_;
} }