170 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						|
#include <filesystem>
 | 
						|
#include "data.hpp"
 | 
						|
#include "toolbox.hpp"
 | 
						|
//#include "config.hpp"
 | 
						|
 | 
						|
template <typename T>
 | 
						|
bool unit_test_cpu_vs_gpu(const np::Array<T>& cpu, const np::Array<T>& gpu) noexcept {
 | 
						|
	if (cpu.shape != gpu.shape) {
 | 
						|
#if __DEBUG
 | 
						|
		fprintf(stderr, "Unequal shape !\n");
 | 
						|
#endif
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	size_t eq = 0;
 | 
						|
	const size_t length = np::prod(cpu.shape);
 | 
						|
	for (size_t i = 0; i < length; ++i)
 | 
						|
		if (cpu[i] == gpu[i])
 | 
						|
			++eq;
 | 
						|
 | 
						|
#if __DEBUG
 | 
						|
	if (eq != length)
 | 
						|
		printf("Incorrect results, Number of equalities : %s/%s <=> %.2f%% !\n", thousand_sep(eq).c_str(), thousand_sep(length).c_str(),
 | 
						|
				static_cast<float64_t>(eq) / static_cast<float64_t>(length) * 100.0);
 | 
						|
#endif
 | 
						|
 | 
						|
	return eq == length;
 | 
						|
}
 | 
						|
 | 
						|
template <typename T>
 | 
						|
bool unit_test_argsort_2d(const np::Array<T>& a, const np::Array<uint16_t>& indices) noexcept {
 | 
						|
	if (a.shape != indices.shape) {
 | 
						|
#if __DEBUG
 | 
						|
		fprintf(stderr, "Unequal shape !\n");
 | 
						|
#endif
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
	size_t correct = a.shape[0]; // First elements are always correctly sorted
 | 
						|
	const size_t total = np::prod(a.shape);
 | 
						|
	for(size_t i = 0; i < total; i += a.shape[1])
 | 
						|
		for(size_t j = 0; j < a.shape[1] - 1; ++j){
 | 
						|
			const size_t k = i + j;
 | 
						|
			if(a[i + indices[k]] <= a[i + indices[k + 1]])
 | 
						|
				++correct;
 | 
						|
		}
 | 
						|
#if __DEBUG
 | 
						|
	if (correct != total)
 | 
						|
		printf("Incorrect results, Number of equalities : %s/%s <=> %.2f%% !\n", thousand_sep(correct).c_str(), thousand_sep(total).c_str(),
 | 
						|
				static_cast<float64_t>(correct) / static_cast<float64_t>(total) * 100.0);
 | 
						|
#endif
 | 
						|
	return correct == total;
 | 
						|
}
 | 
						|
 | 
						|
template <typename T, typename F, typename... Args>
 | 
						|
T benchmark_function(const char* const step_name, const int32_t& column_width, const F& fnc, Args &&...args) noexcept {
 | 
						|
#if __DEBUG == false
 | 
						|
	fprintf(stderr, "%s...\r", step_name);
 | 
						|
	fflush(stderr); // manual flush is mandatory, otherwise it will not be shown immediately because the output is buffered
 | 
						|
#endif
 | 
						|
	const std::chrono::system_clock::time_point start = perf_counter_ns();
 | 
						|
	const T res = fnc(std::forward<Args>(args)...);
 | 
						|
	const long long time_spent = duration_ns(perf_counter_ns() - start);
 | 
						|
	formatted_row<3>({ column_width, -18, 29 }, { step_name, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() });
 | 
						|
	return res;
 | 
						|
}
 | 
						|
 | 
						|
template <typename F, typename... Args>
 | 
						|
void benchmark_function_void(const char* const step_name, const int32_t& column_width, const F& fnc, Args &&...args) noexcept {
 | 
						|
#if __DEBUG == false
 | 
						|
	fprintf(stderr, "%s...\r", step_name);
 | 
						|
	fflush(stderr); // manual flush is mandatory, otherwise it will not be shown immediately because the output is buffered
 | 
						|
#endif
 | 
						|
	const std::chrono::system_clock::time_point start = perf_counter_ns();
 | 
						|
	fnc(std::forward<Args>(args)...);
 | 
						|
	const long long time_spent = duration_ns(perf_counter_ns() - start);
 | 
						|
	formatted_row<3>({ column_width, -18, 29 }, { step_name, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() });
 | 
						|
}
 | 
						|
 | 
						|
template <typename T, typename F, typename... Args>
 | 
						|
np::Array<T> state_saver(const char* const step_name, const int32_t& column_width, const char* const filename, const bool& force_redo, const bool& save_state, const char* const out_dir, const F& fnc, Args &&...args) noexcept {
 | 
						|
	char filepath[BUFFER_SIZE] = { 0 };
 | 
						|
	snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename);
 | 
						|
 | 
						|
	np::Array<T> bin;
 | 
						|
	if (!std::filesystem::exists(filepath) || force_redo) {
 | 
						|
		//bin = std::move(benchmark_function<np::Array<T>>(step_name, column_width, fnc, std::forward<Args>(args)...));
 | 
						|
		bin = benchmark_function<np::Array<T>>(step_name, column_width, fnc, std::forward<Args>(args)...);
 | 
						|
		if(save_state){
 | 
						|
#if __DEBUG == false
 | 
						|
			fprintf(stderr, "Saving results of %s\r", step_name);
 | 
						|
			fflush(stderr);
 | 
						|
#endif
 | 
						|
			save<T>(bin, filepath);
 | 
						|
#if __DEBUG == false
 | 
						|
			fprintf(stderr, "%*c\r", 100, ' '); // Clear previous clear
 | 
						|
			fflush(stderr);
 | 
						|
#endif
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
#if __DEBUG == false
 | 
						|
		fprintf(stderr, "Loading results of %s\r", step_name);
 | 
						|
		fflush(stderr);
 | 
						|
#endif
 | 
						|
		//bin = std::move(load<T>(filepath));
 | 
						|
		bin = load<T>(filepath);
 | 
						|
		formatted_row<3>({ column_width, -18, 29 }, { step_name, "None", "loaded saved state" });
 | 
						|
	}
 | 
						|
	return bin;
 | 
						|
}
 | 
						|
 | 
						|
template <typename T, size_t N, typename F, typename... Args>
 | 
						|
std::array<np::Array<T>, N> state_saver(const char* const step_name, const int32_t& column_width, const std::vector<const char*>& filenames, const bool& force_redo, const bool& save_state, const char* const out_dir, const F& fnc, Args &&...args) noexcept {
 | 
						|
	char filepath[BUFFER_SIZE] = { 0 };
 | 
						|
	bool abs = false;
 | 
						|
	for (const char* const filename : filenames){
 | 
						|
		snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename);
 | 
						|
		if (!std::filesystem::exists(filepath)) {
 | 
						|
			abs = true;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	std::array<np::Array<T>, N> bin;
 | 
						|
	if (abs || force_redo) {
 | 
						|
		//bin = std::move(benchmark_function<std::array<np::Array<T>, N>>(step_name, column_width, fnc, std::forward<Args>(args)...));
 | 
						|
		bin = benchmark_function<std::array<np::Array<T>, N>>(step_name, column_width, fnc, std::forward<Args>(args)...);
 | 
						|
		if (save_state){
 | 
						|
#if __DEBUG == false
 | 
						|
			fprintf(stderr, "Saving results of %s\r", step_name);
 | 
						|
			fflush(stderr);
 | 
						|
#endif
 | 
						|
			size_t i = 0;
 | 
						|
			for (const char* const filename : filenames){
 | 
						|
				snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename);
 | 
						|
				save<T>(bin[i++], filepath);
 | 
						|
			}
 | 
						|
#if __DEBUG == false
 | 
						|
			fprintf(stderr, "%*c\r", 100, ' '); // Clear previous print
 | 
						|
			fflush(stderr);
 | 
						|
#endif
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
#if __DEBUG == false
 | 
						|
		fprintf(stderr, "Loading results of %s\r", step_name);
 | 
						|
		fflush(stderr);
 | 
						|
#endif
 | 
						|
		size_t i = 0;
 | 
						|
			bin[i++] = std::move(load<T>(filepath));
 | 
						|
		for (const char* const filename : filenames){
 | 
						|
			snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename);
 | 
						|
		}
 | 
						|
		formatted_row<3>({ column_width, -18, 29 }, { step_name, "None", "loaded saved state" });
 | 
						|
	}
 | 
						|
	return bin;
 | 
						|
}
 | 
						|
 | 
						|
np::Array<uint16_t> argsort_2d_cpu(const np::Array<int32_t>&) noexcept;
 | 
						|
np::Array<uint8_t> build_features(const uint16_t&, const uint16_t&) noexcept;
 | 
						|
np::Array<int32_t> select_percentile(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
 | 
						|
np::Array<uint8_t> classify_viola_jones(const np::Array<float64_t>&, const np::Array<float64_t>&, const np::Array<int32_t>&) noexcept;
 | 
						|
np::Array<float64_t> init_weights(const np::Array<uint8_t>&) noexcept;
 | 
						|
std::tuple<int32_t, float64_t, np::Array<float64_t>> select_best(const np::Array<float64_t>&, const np::Array<float64_t>&, const np::Array<int32_t>&,
 | 
						|
								const np::Array<uint8_t>&) noexcept;
 | 
						|
std::array<np::Array<float64_t>, 2> train_viola_jones(const size_t&, const np::Array<int32_t>&, const np::Array<uint16_t>&, const np::Array<uint8_t>&) noexcept;
 | 
						|
float64_t accuracy_score(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
 | 
						|
float64_t precision_score(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
 | 
						|
float64_t recall_score(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
 | 
						|
float64_t f1_score(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
 | 
						|
std::tuple<uint16_t, uint16_t, uint16_t, uint16_t> confusion_matrix(const np::Array<uint8_t>&, const np::Array<uint8_t>&) noexcept;
 |