Skip to content

Commit

Permalink
Add C++ examples, C++ CI (#10)
Browse files Browse the repository at this point in the history
* Add C++ examples, C++ CI

* Remove extraneous entry from CMake

* Use g++-14 for C++ CI

* Minor fix

* Verbose build for debugging

* Use gcc 13

* GCC 12
  • Loading branch information
BenBrock authored Aug 28, 2024
1 parent 705f775 commit 122cce8
Show file tree
Hide file tree
Showing 16 changed files with 1,009 additions and 3 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ jobs:
- name: CMake
run: |
sudo apt-get update
sudo apt-get install libhdf5-dev
cmake -B build
sudo apt-get install libhdf5-dev g++-12
CXX=g++-12 cmake -B build
- name: Build
run: make -C build -j `nproc`
run: VERBOSE=true make -C build -j `nproc`
- name: Test
run: ctest --test-dir ./build/test/bash
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ cmake_policy(SET CMP0079 NEW)

set(CMAKE_C_STANDARD 11)

set(CMAKE_CXX_STANDARD 20)

set(CMAKE_C_FLAGS "-O3 -march=native")

add_subdirectory(include)
Expand Down
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ add_example(bsp-ls)
add_example(benchmark_read)
add_example(benchmark_read_parallel)
add_example(benchmark_write)

add_subdirectory(cpp)
15 changes: 15 additions & 0 deletions examples/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function(add_example example_name)
add_executable(${example_name}-cpp ${example_name}.cpp)
target_link_libraries(${example_name}-cpp binsparse-rc)
endfunction()

add_example(simple_matrix_write)
add_example(simple_matrix_read)
add_example(simple_read)
add_example(simple_write)
add_example(mtx2bsp)
add_example(bsp2mtx)
add_example(check_equivalence)
add_example(bsp-ls)
add_example(benchmark_read)
add_example(benchmark_write)
123 changes: 123 additions & 0 deletions examples/cpp/benchmark_read.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include <binsparse/binsparse.h>
#include <stdlib.h>
#include <time.h>

double gettime() {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return ((double) time.tv_sec) + ((double) 1e-9) * time.tv_nsec;
}

int compar(const void* a, const void* b) {
double x = *((const double*) a);
double y = *((const double*) b);

double diff = x - y;

if (diff > 0) {
return 1;
} else if (diff < 0) {
return -1;
} else {
return 0;
}
}

double compute_variance(double* x, size_t n) {
double sum = 0;

for (size_t i = 0; i < n; i++) {
sum += x[i];
}

double mean = sum / n;

double sum_of_squares = 0;
for (size_t i = 0; i < n; i++) {
sum_of_squares += (x[i] - mean) * (x[i] - mean);
}

return sum_of_squares / (n - 1);
}

void flush_cache() {
#ifdef __APPLE__
system("bash -c \"sync && sudo purge\"");
#elif __linux__
system("bash -c \"sync\" && sudo echo 3 > /proc/sys/vm/drop_caches");
#else
static_assert(false);
#endif
}

int main(int argc, char** argv) {
if (argc < 2) {
fprintf(stderr, "usage: ./benchmark_read [file_name.h5]\n");
return 1;
}

char* file_name = argv[1];

printf("Opening %s\n", file_name);

const int num_trials = 1;

double durations[num_trials];

size_t nbytes = 0;

// To flush the filesystem cache before each trial, change to `true`.
bool cold_cache = false;

for (size_t i = 0; i < num_trials; i++) {
if (cold_cache) {
flush_cache();
}
double begin = gettime();
bsp_matrix_t mat = bsp_read_matrix(file_name, NULL);
double end = gettime();
durations[i] = end - begin;
nbytes = bsp_matrix_nbytes(mat);
bsp_destroy_matrix_t(mat);
}

printf("[");
for (size_t i = 0; i < num_trials; i++) {
printf("%lf", durations[i]);
if (i + 1 < num_trials) {
printf(", ");
}
}
printf("]\n");

qsort(durations, num_trials, sizeof(double), compar);

double variance = compute_variance(durations, num_trials);

double median_time = durations[num_trials / 2];

printf("Read file in %lf seconds\n", median_time);

if (num_trials > 1) {
printf("Variance is %lf seconds, standard devication is %lf seconds\n",
variance, sqrt(variance));
}

double gbytes = ((double) nbytes) / 1024 / 1024 / 1024;
double gbytes_s = gbytes / median_time;

printf("Achieved %lf GiB/s\n", gbytes_s);

printf("[");
for (size_t i = 0; i < num_trials; i++) {
printf("%lf", durations[i]);
if (i + 1 < num_trials) {
printf(", ");
}
}
printf("]\n");

printf("FORPARSER: %s,%lf,%lf\n", file_name, median_time, gbytes_s);

return 0;
}
170 changes: 170 additions & 0 deletions examples/cpp/benchmark_write.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#include <binsparse/binsparse.h>
#include <stdlib.h>
#include <time.h>

double gettime() {
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return ((double) time.tv_sec) + ((double) 1e-9) * time.tv_nsec;
}

int compar(const void* a, const void* b) {
double x = *((const double*) a);
double y = *((const double*) b);

double diff = x - y;

if (diff > 0) {
return 1;
} else if (diff < 0) {
return -1;
} else {
return 0;
}
}

double compute_variance(double* x, size_t n) {
double sum = 0;

for (size_t i = 0; i < n; i++) {
sum += x[i];
}

double mean = sum / n;

double sum_of_squares = 0;
for (size_t i = 0; i < n; i++) {
sum_of_squares += (x[i] - mean) * (x[i] - mean);
}

return sum_of_squares / (n - 1);
}

void flush_cache() {
#ifdef __APPLE__
system("bash -c \"sync && sudo purge\"");
#elif __linux__
system("bash -c \"sync\" && sudo echo 3 > /proc/sys/vm/drop_caches");
#else
static_assert(false);
#endif
}

void flush_writes() {
#ifdef __APPLE__
system("bash -c \"sync\"");
#elif __linux__
system("bash -c \"sync\"");
#else
static_assert(false);
#endif
}

void delete_file(const char* file_name) {
char command[2048];
snprintf(command, 2047, "rm %s", file_name);
system(command);
}

int main(int argc, char** argv) {
if (argc < 2) {
fprintf(stderr,
"usage: ./benchmark_read [file_name.h5] [scratch_space] [optional: "
"compression_level]\n");
return 1;
}

char* file_name = argv[1];
char* scratch_space = argv[2];

int compression_level = 0;

if (argc >= 4) {
compression_level = atoi(argv[3]);
}

printf("Opening %s\n", file_name);

const int num_trials = 1;

double durations[num_trials];

bsp_matrix_t mat = bsp_read_matrix(file_name, NULL);
size_t nbytes = bsp_matrix_nbytes(mat);

char output_filename[2048];
strncpy(output_filename, scratch_space, 2047);
strncpy(output_filename + strlen(scratch_space), "/benchmark_write_file_n.h5",
2047 - strlen(scratch_space));

// Current output name logic does not do much.
assert(num_trials <= 10);

// To flush the filesystem cache before each trial, change to `true`.
bool cold_cache = false;

// To flush each write to the filesystem and include this in the timing,
// change to `true`.
bool flush_each_write = true;

for (size_t i = 0; i < num_trials; i++) {
if (cold_cache) {
flush_cache();
}

output_filename[strlen(scratch_space) + 21] = '0' + i;
printf("Writing to file %s\n", output_filename);

double begin = gettime();
bsp_write_matrix(output_filename, mat, NULL, NULL, compression_level);

if (flush_each_write) {
flush_writes();
}

double end = gettime();
durations[i] = end - begin;

delete_file(output_filename);
}

printf("[");
for (size_t i = 0; i < num_trials; i++) {
printf("%lf", durations[i]);
if (i + 1 < num_trials) {
printf(", ");
}
}
printf("]\n");

qsort(durations, num_trials, sizeof(double), compar);

double variance = compute_variance(durations, num_trials);

double median_time = durations[num_trials / 2];

printf("Wrote file in %lf seconds\n", median_time);

if (num_trials > 1) {
printf("Variance is %lf seconds, standard devication is %lf seconds\n",
variance, sqrt(variance));
}

double gbytes = ((double) nbytes) / 1024 / 1024 / 1024;
double gbytes_s = gbytes / median_time;

printf("Achieved %lf GiB/s\n", gbytes_s);

printf("[");
for (size_t i = 0; i < num_trials; i++) {
printf("%lf", durations[i]);
if (i + 1 < num_trials) {
printf(", ");
}
}
printf("]\n");

printf("FORPARSER: %s,%lf,%lf\n", file_name, median_time, gbytes_s);

return 0;
}
Loading

0 comments on commit 122cce8

Please sign in to comment.