From 1f65ef6ca82de1f8e2112d525b28dcbbdd92b224 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 09:15:03 -0800 Subject: [PATCH 01/12] Export dl_read_partial and properly clean between rebuilds --- Makefile | 14 +++++++------- combined/libssu.c | 7 +++++++ src/api.hpp | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 8b04e98..0ad6ec1 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ clean: ########### api api: - cd src && make api + cd src && make clean && make api api_cpu_basic: export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make clean && make api @@ -43,12 +43,12 @@ api_nv_avx2: . ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && make clean && make api api_combined: - cd combined && make api + cd combined && make clean && make api ########### main main: - cd src && make main + cd src && make clean && make main install_main: cd src && make install @@ -73,13 +73,13 @@ install_combined: ########### test test_binaries: - cd src && make test_binaries - cd test && make test_binaries + cd src && make clean && make test_binaries + cd test && make clean && make test_binaries test_binaries_nv: - . ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make test_binaries + . ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make clean && make test_binaries # use the default compiler for the test subdir as it tests the combined shlib - cd test && make test_binaries + cd test && make clean && make test_binaries test: cd src && make test diff --git a/combined/libssu.c b/combined/libssu.c index b410e2c..26d9d1b 100644 --- a/combined/libssu.c +++ b/combined/libssu.c @@ -525,6 +525,7 @@ static ComputeStatus (*dl_partial)(const char*, const char*, const char*, bool, static MergeStatus (*dl_merge_partial_to_mmap_matrix)(partial_dyn_mat_t**, int, const char *, mat_full_fp64_t**) = NULL; static MergeStatus (*dl_merge_partial_to_mmap_matrix_fp32)(partial_dyn_mat_t**, int, const char *, mat_full_fp32_t**) = NULL; static MergeStatus (*dl_validate_partial)(const partial_dyn_mat_t* const *, int); +static IOStatus (*dl_read_partial)(const char*, partial_mat_t**); static IOStatus (*dl_read_partial_header)(const char*, partial_dyn_mat_t**); static IOStatus (*dl_read_partial_one_stripe)(partial_dyn_mat_t*, uint32_t); static IOStatus (*dl_write_partial)(const char*, const partial_mat_t*); @@ -558,6 +559,12 @@ MergeStatus validate_partial(const partial_dyn_mat_t* const * partial_mats, int return (*dl_validate_partial)(partial_mats,n_partials); } +IOStatus read_partial(const char* input_filename, partial_mat_t** result_out) { + cond_ssu_load("read_partial", (void **) &dl_read_partial); + + return (*dl_read_partial)(input_filename,result_out); +} + IOStatus read_partial_header(const char* input_filename, partial_dyn_mat_t** result_out) { cond_ssu_load("read_partial_header", (void **) &dl_read_partial_header); diff --git a/src/api.hpp b/src/api.hpp index 0417c98..7d15476 100644 --- a/src/api.hpp +++ b/src/api.hpp @@ -765,7 +765,7 @@ EXTERN IOStatus write_partial(const char* filename, const partial_mat_t* result) * bad_header : header seems malformed * unexpected_end : format end not found in expected location */ -IOStatus read_partial(const char* filename, partial_mat_t** result); +EXTERN IOStatus read_partial(const char* filename, partial_mat_t** result); /* Read a partial matrix object header * From ef3298973db1002f4c9ddef519e35dea66e86bcf Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 09:41:17 -0800 Subject: [PATCH 02/12] Use shared library in test_api. Deprecate merge_partial, since not use anywhere anymore --- Makefile | 7 +------ src/Makefile | 4 ++-- src/api.cpp | 4 +++- src/api.hpp | 9 +++++++-- src/test_api.cpp | 25 ++++++++++++++----------- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 0ad6ec1..9028042 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ all: api install main install_main test_binaries else # Note: important that all_nv is after all_cpu_basic and all_nv_avx2 for tests to work -all: all_cpu_basic all_nv_avx2 all_nv all_combined test_binaries_nv +all: all_cpu_basic all_nv_avx2 all_nv all_combined test_binaries all_cpu_basic: api_cpu_basic install_cpu_basic @@ -76,11 +76,6 @@ test_binaries: cd src && make clean && make test_binaries cd test && make clean && make test_binaries -test_binaries_nv: - . ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make clean && make test_binaries - # use the default compiler for the test subdir as it tests the combined shlib - cd test && make clean && make test_binaries - test: cd src && make test cd test && make test diff --git a/src/Makefile b/src/Makefile index d9f7aaf..62fb5c7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -150,8 +150,8 @@ test_su: test_su.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsample $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_su.cpp -o test_su tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o skbio_alt.o api.o -llz4 $(BLASLIB) -lpthread test_ska: test_ska.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o unifrac.o skbio_alt.o api.o $(UNIFRAC_FILES) $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_ska.cpp -o test_ska skbio_alt.o tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o api.o -llz4 $(BLASLIB) -lpthread -test_api: test_api.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o unifrac.o skbio_alt.o api.o $(UNIFRAC_FILES) - $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_api.cpp -o test_api tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o skbio_alt.o api.o -llz4 $(BLASLIB) -lpthread +test_api: test_api.cpp api.hpp test_helper.hpp biom.hpp $(PREFIX)/lib/lib$(SSU).so + $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_api.cpp -o $@ -l$(SSU) $(SSU): su.cpp api.hpp biom.hpp $(PREFIX)/lib/lib$(SSU).so $(CXX) $(CPPFLAGS) $(EXEFLAGS) su.cpp -o $@ -l$(SSU) diff --git a/src/api.cpp b/src/api.cpp index 30e86bb..116730b 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -2272,7 +2272,8 @@ MergeStatus validate_partial(const partial_dyn_mat_t* const * partial_mats, int return check_partial(partial_mats, n_partials, true); } - +#if 0 +// DEPRECATED, not used by anyone anymore MergeStatus merge_partial(partial_mat_t** partial_mats, int n_partials, unsigned int dummy, mat_t** result) { MergeStatus err = check_partial(partial_mats, n_partials, false); if (err!=merge_okay) return err; @@ -2299,6 +2300,7 @@ MergeStatus merge_partial(partial_mat_t** partial_mats, int n_partials, unsigned return merge_okay; } +#endif // Will keep only the strictly necessary stripes in memory... reading just in time class PartialStripes : public su::ManagedStripes { diff --git a/src/api.hpp b/src/api.hpp index 7d15476..b2ffe29 100644 --- a/src/api.hpp +++ b/src/api.hpp @@ -803,7 +803,9 @@ EXTERN IOStatus read_partial_one_stripe(partial_dyn_mat_t* result, uint32_t stri */ EXTERN MergeStatus validate_partial(const partial_dyn_mat_t* const * partial_mats, int n_partials); +#if 0 /* Merge partial results + * DEPRECATED, not used by anyone anymore * * results an array of partial_mat_t*, the buffers will be destroyed in the process * n_partials number of partial mats @@ -817,8 +819,10 @@ EXTERN MergeStatus validate_partial(const partial_dyn_mat_t* const * partial_mat * square_mismatch : inconsistency on denotation of square matrix */ MergeStatus merge_partial(partial_mat_t** partial_mats, int n_partials, unsigned int dummy, mat_t** result); +#endif /* Merge partial results + * DEPRECATED, for backwards compatibility only, use the mmap version instead * * partial_mats an array of partial_dyn_mat_t* * n_partials number of partial mats @@ -834,6 +838,7 @@ MergeStatus merge_partial(partial_mat_t** partial_mats, int n_partials, unsigned MergeStatus merge_partial_to_matrix(partial_dyn_mat_t* * partial_mats, int n_partials, mat_full_fp64_t** result); /* Merge partial results + * DEPRECATED, for backwards compatibility only, use the mmap version instead * * partial_mats an array of partial_dyn_mat_t* * n_partials number of partial mats @@ -853,7 +858,7 @@ MergeStatus merge_partial_to_matrix_fp32(partial_dyn_mat_t* * partial_mats, int * * partial_mats an array of partial_dyn_mat_t* * n_partials number of partial mats - * mmap_dir Where to host the mmap file + * mmap_dir Where to host the mmap file, use NULL if no mmap * result the full matrix, output parameters, this is initialized in the method so using ** * * The following error codes are returned: @@ -869,7 +874,7 @@ EXTERN MergeStatus merge_partial_to_mmap_matrix(partial_dyn_mat_t* * partial_mat * * partial_mats an array of partial_dyn_mat_t* * n_partials number of partial mats - * mmap_dir Where to host the mmap file + * mmap_dir Where to host the mmap file, use NULL if no mmap * result the full matrix, output parameters, this is initialized in the method so using ** * * The following error codes are returned: diff --git a/src/test_api.cpp b/src/test_api.cpp index 9e73387..a190b04 100644 --- a/src/test_api.cpp +++ b/src/test_api.cpp @@ -242,6 +242,8 @@ void test_read_write_partial_mat() { SUITE_END(); } +#if 0 +// DEPRECATED: Not used by anyone anymore void test_merge_partial_mat() { SUITE_START("test merge partial_mat_t"); @@ -336,6 +338,7 @@ void test_merge_partial_mat() { SUITE_END(); } +#endif void test_merge_partial_dyn_mat() { SUITE_START("test merge partial_dyn_mat_t"); @@ -351,7 +354,7 @@ void test_merge_partial_dyn_mat() { pms[1] = pm2; mat_full_fp64_t* obs = NULL; - merge_status err = merge_partial_to_matrix(pms, 2, &obs); + merge_status err = merge_partial_to_mmap_matrix(pms, 2, NULL, &obs); ASSERT(err == merge_okay); ASSERT(obs->n_samples == exp->n_samples); for(unsigned int i = 0; i < (obs->n_samples*obs->n_samples); i++) { @@ -378,7 +381,7 @@ void test_merge_partial_dyn_mat() { mat_full_fp32_t* exp2 = mat_full_three_rep(); mat_full_fp32_t *obs2 = NULL; - err = merge_partial_to_matrix_fp32(pms, 2, &obs2); + err = merge_partial_to_mmap_matrix_fp32(pms, 2, NULL, &obs2); ASSERT(err == merge_okay); ASSERT(obs2->n_samples == exp2->n_samples); for(unsigned int i = 0; i < (obs2->n_samples*obs2->n_samples); i++) { @@ -421,27 +424,27 @@ void test_merge_partial_dyn_mat() { pms_err[0] = pm2; pms_err[1] = pm3; - err = merge_partial_to_matrix(pms_err, 3, &obs); + err = merge_partial_to_mmap_matrix(pms_err, 3, NULL, &obs); ASSERT(err == incomplete_stripe_set); pm2->stripe_start = 2; pm2->stripe_stop = 6; - err = merge_partial_to_matrix(pms_err, 3, &obs); + err = merge_partial_to_mmap_matrix(pms_err, 3, NULL, &obs); ASSERT(err == stripes_overlap); pm2->stripe_start = 3; pm2->sample_ids[2][0] = 'X'; - err = merge_partial_to_matrix(pms_err, 3, &obs); + err = merge_partial_to_mmap_matrix(pms_err, 3, NULL, &obs); ASSERT(err == sample_id_consistency); pm2->sample_ids[2][0] = 'C'; pm3->n_samples = 2; - err = merge_partial_to_matrix(pms_err, 3, &obs); + err = merge_partial_to_mmap_matrix(pms_err, 3, NULL, &obs); ASSERT(err == partials_mismatch); pm3->n_samples = 6; pm3->stripe_total = 12; - err = merge_partial_to_matrix(pms_err, 3, &obs); + err = merge_partial_to_mmap_matrix(pms_err, 3, NULL, &obs); ASSERT(err == partials_mismatch); /* @@ -449,7 +452,7 @@ void test_merge_partial_dyn_mat() { pm3->is_upper_triangle = false; pm3->stripe_total = 9; - err = merge_partial_to_matrix(pms_err, 3, &obs); + err = merge_partial_to_mmap_matrix(pms_err, 3, NULL, &obs); ASSERT(err == square_mismatch); */ @@ -490,7 +493,7 @@ void test_merge_partial_io() { pms[1] = pm2; mat_full_fp64_t* obs = NULL; - merge_status err = merge_partial_to_matrix(pms, 2, &obs); + merge_status err = merge_partial_to_mmap_matrix(pms, 2, NULL, &obs); ASSERT(err == merge_okay); ASSERT(obs->n_samples == exp->n_samples); for(unsigned int i = 0; i < (obs->n_samples*obs->n_samples); i++) { @@ -522,7 +525,7 @@ void test_merge_partial_io() { mat_full_fp32_t* exp2 = mat_full_three_rep(); mat_full_fp32_t *obs2 = NULL; - err = merge_partial_to_matrix_fp32(pms, 2, &obs2); + err = merge_partial_to_mmap_matrix_fp32(pms, 2, NULL, &obs2); ASSERT(err == merge_okay); ASSERT(obs2->n_samples == exp2->n_samples); for(unsigned int i = 0; i < (obs2->n_samples*obs2->n_samples); i++) { @@ -690,7 +693,7 @@ int main(int argc, char** argv) { //test_write_mat(); //test_read_mat(); test_read_write_partial_mat(); - test_merge_partial_mat(); + //test_merge_partial_mat(); test_merge_partial_dyn_mat(); test_merge_partial_io(); test_merge_partial_mmap(); From f9a2aafcd08faf75f591300ce790d7de3a564fbd Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 09:46:18 -0800 Subject: [PATCH 03/12] test_ska does not use the unifrac object files --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 62fb5c7..c4fd28a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -148,8 +148,8 @@ test_binaries: test_su test_ska test_api test_su: test_su.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o unifrac.o skbio_alt.o api.o $(UNIFRAC_FILES) $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_su.cpp -o test_su tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o skbio_alt.o api.o -llz4 $(BLASLIB) -lpthread -test_ska: test_ska.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o unifrac.o skbio_alt.o api.o $(UNIFRAC_FILES) - $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_ska.cpp -o test_ska skbio_alt.o tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o api.o -llz4 $(BLASLIB) -lpthread +test_ska: test_ska.cpp skbio_alt.hpp api.hpp test_helper.hpp biom.hpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o skbio_alt.o api.o + $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_ska.cpp -o test_ska skbio_alt.o tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o api.o -llz4 $(BLASLIB) -lpthread test_api: test_api.cpp api.hpp test_helper.hpp biom.hpp $(PREFIX)/lib/lib$(SSU).so $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_api.cpp -o $@ -l$(SSU) From 2d106e49131c886f2bb175b26ffe129a2a80fc1d Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 10:02:09 -0800 Subject: [PATCH 04/12] Create an intermediate archive file to avoid dependencies for functions we do not use --- src/Makefile | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index c4fd28a..d919b29 100644 --- a/src/Makefile +++ b/src/Makefile @@ -148,8 +148,16 @@ test_binaries: test_su test_ska test_api test_su: test_su.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o unifrac.o skbio_alt.o api.o $(UNIFRAC_FILES) $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_su.cpp -o test_su tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o skbio_alt.o api.o -llz4 $(BLASLIB) -lpthread -test_ska: test_ska.cpp skbio_alt.hpp api.hpp test_helper.hpp biom.hpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o skbio_alt.o api.o - $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_ska.cpp -o test_ska skbio_alt.o tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o api.o -llz4 $(BLASLIB) -lpthread + +# Create an archive, so we do not need dependencies for functions we do not use +test_ska_deps.a: tree.o tsv.o biom.o biom_inmem.o biom_subsampled.o skbio_alt.o api.o + rm -f $@ + ar -r $@ $^ + +# Not invoking the unifrac acc code, so we do not need to use the shlib +test_ska: test_ska.cpp skbio_alt.hpp api.hpp test_helper.hpp biom.hpp test_ska_deps.a + $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_ska.cpp -o test_ska test_ska_deps.a -llz4 $(BLASLIB) -lpthread + test_api: test_api.cpp api.hpp test_helper.hpp biom.hpp $(PREFIX)/lib/lib$(SSU).so $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_api.cpp -o $@ -l$(SSU) @@ -165,7 +173,6 @@ lib$(SSU).so: tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o api.o: api.cpp api.hpp unifrac.hpp skbio_alt.hpp biom.hpp biom_inmem.hpp biom_subsampled.hpp tree.hpp tsv.hpp $(CXX) $(CPPFLAGS) api.cpp -c -o api.o -fPIC - unifrac_task_noclass.cpp: unifrac_task_impl.hpp python3 generate_unifrac_task_noclass.py >unifrac_task_noclass.cpp @@ -226,5 +233,5 @@ rapi_test: tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o sk rm -f *.o clean: - -rm -f *.o $(SSU) $(FPD) test_su test_ska test_api lib$(SSU).so unifrac_task_noclass.cpp + -rm -f *.o $(SSU) $(FPD) *.a test_su test_ska test_api lib$(SSU).so unifrac_task_noclass.cpp From a1a2c5bf33d7eb30b5ec6af29d0ef33772f11ba4 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 11:37:39 -0800 Subject: [PATCH 05/12] Add API-based unifrac tests in test_su --- src/test_su.cpp | 219 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 3 deletions(-) diff --git a/src/test_su.cpp b/src/test_su.cpp index a04de73..054505e 100644 --- a/src/test_su.cpp +++ b/src/test_su.cpp @@ -5,6 +5,53 @@ #include "unifrac_internal.hpp" #include "test_helper.hpp" +// copy of internal function in api... repeated here for testing +uint64_t _testv_comb_2(uint64_t N) { + // based off of _comb_int_long + // https://github.com/scipy/scipy/blob/v0.19.1/scipy/special/_comb.pyx + + // Compute binom(N, k) for integers. + // + // we're disregarding overflow as that practically should not + // happen unless the number of samples processed is in excess + // of 4 billion + uint64_t val, j, M, nterms; + uint64_t k = 2; + + M = N + 1; + nterms = k < (N - k) ? k : N - k; + + val = 1; + + for(j = 1; j < nterms + 1; j++) { + val *= M - j; + val /= j; + } + return val; +} + +// minor variant of internal function in api... repeated here for testing +void _testv_stripes_to_condensed_form(double* stripes[], uint32_t n, uint32_t m, double* cf) { + uint64_t comb_N = _testv_comb_2(n); + for(unsigned int stripe = 0; stripe < m; stripe++) { + // compute the (i, j) position of each element in each stripe + uint64_t i = 0; + uint64_t j = stripe + 1; + for(uint64_t k = 0; k < n; k++, i++, j++) { + if(j == n) { + i = 0; + j = n - (stripe + 1); + } + // determine the position in the condensed form vector for a given (i, j) + // based off of + // https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.squareform.html + uint64_t comb_N_minus_i = _testv_comb_2(n - i); + cf[comb_N - comb_N_minus_i + (j - i - 1)] = stripes[stripe][k]; + } + } +} + + void test_bptree_simple_result(const su::BPTree &tree) { unsigned int exp_nparens = 8; @@ -853,12 +900,21 @@ void test_unifrac_stripes_to_condensed_form_even() { /* *, *, *, *, *, *, *, *, 0, */ 44}; /* *, *, *, *, *, *, *, *, *, *, 0 */ - double *obs = (double*)malloc(sizeof(double) * 45); + double *obs = NULL; + obs = (double*)malloc(sizeof(double) * 45); su::stripes_to_condensed_form(stripes, 10, obs, 0, 5); for(unsigned int i = 0; i < 45; i++) { ASSERT(exp[i] == obs[i]); } free(obs); + // test internal version, too + double* cstripes[] = {s1, s2, s3, s4 ,s5}; + obs = (double*)malloc(sizeof(double) * 45); + _testv_stripes_to_condensed_form(cstripes, 10, 5, obs); + for(unsigned int i = 0; i < 45; i++) { + ASSERT(exp[i] == obs[i]); + } + free(obs); SUITE_END(); } @@ -887,12 +943,21 @@ void test_unifrac_stripes_to_condensed_form_odd() { /*29, 32, 49, 44, 36, 26, 14, 8, 0, */ 9, 12, /*11, 30, 31, 50, 45, 35, 27, 13, 9, 0,*/ 10}; /* 0, 1, 2, 3, 4, 46, 34, 28, 12, 10, 0}; */ - double *obs = (double*)malloc(sizeof(double) * 55); + double *obs = NULL; + obs = (double*)malloc(sizeof(double) * 55); su::stripes_to_condensed_form(stripes, 11, obs, 0, 5); for(unsigned int i = 0; i < 55; i++) { ASSERT(exp[i] == obs[i]); } free(obs); + // test internal version, too + double* cstripes[] = {s1, s2, s3, s4 ,s5}; + obs = (double*)malloc(sizeof(double) * 55); + _testv_stripes_to_condensed_form(cstripes, 11, 5, obs); + for(unsigned int i = 0; i < 55; i++) { + ASSERT(exp[i] == obs[i]); + } + free(obs); SUITE_END(); } @@ -919,12 +984,21 @@ void test_unifrac_stripes_to_condensed_form_odd2() { /*47, 42, 38, 24, 16, 6, 0, */ 7, 12, /*47, 42, 38, 24, 16, 6, 7, 0, */ 8}; /* 0, 1, 2, 3, 4, 46, 34, 8, 8, 0}; */ - double *obs = (double*)malloc(sizeof(double) * 36); + double *obs = NULL; + obs = (double*)malloc(sizeof(double) * 36); su::stripes_to_condensed_form(stripes, 9, obs, 0, 5); for(unsigned int i = 0; i < 36; i++) { ASSERT(exp[i] == obs[i]); } free(obs); + // test internal version, too + double* cstripes[] = {s1, s2, s3, s4 ,s5}; + obs = (double*)malloc(sizeof(double) * 36); + _testv_stripes_to_condensed_form(cstripes, 9, 5, obs); + for(unsigned int i = 0; i < 36; i++) { + ASSERT(exp[i] == obs[i]); + } + free(obs); SUITE_END(); } @@ -1261,6 +1335,22 @@ void test_unnormalized_weighted_unifrac() { } free(strides[i]); } + + // repeat using the API + double* cstripes[] = {stride1, stride2, stride3}; + mat_t *res = NULL; + ComputeStatus rc = one_off("test.biom", "test.tre", + "weighted_unnormalized", false, 0.0, + false, 1, &res); + ASSERT(rc == okay); + double *expS = (double*)malloc(sizeof(double) * 18); + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + free(expS); + destroy_mat(&res); + SUITE_END(); } @@ -1370,6 +1460,49 @@ void test_generalized_unifrac() { free(d0_strides[i]); free(d05_strides[i]); } + + // repeat using the API + double* cstripes[3]; + double *expS = (double*)malloc(sizeof(double) * 18); + + mat_t *res = NULL; + ComputeStatus rc; + + rc = one_off("test.biom", "test.tre", + "generalized", false, 1.0, + false, 1, &res); + ASSERT(rc == okay); + cstripes[0] = w_stride1; cstripes[1] = w_stride2; cstripes[2] = w_stride3; + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + destroy_mat(&res); + + rc = one_off("test.biom", "test.tre", + "generalized", false, 0.0, + false, 1, &res); + ASSERT(rc == okay); + cstripes[0] = d0_stride1; cstripes[1] = d0_stride2; cstripes[2] = d0_stride3; + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + destroy_mat(&res); + + rc = one_off("test.biom", "test.tre", + "generalized", false, 0.5, + false, 1, &res); + ASSERT(rc == okay); + cstripes[0] = d05_stride1; cstripes[1] = d05_stride2; cstripes[2] = d05_stride3; + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + destroy_mat(&res); + + free(expS); + SUITE_END(); } @@ -1421,6 +1554,22 @@ void test_vaw_unifrac_weighted_normalized() { } free(w_strides[i]); } + + // repeat using the API + double* cstripes[] = {w_stride1, w_stride2, w_stride3}; + mat_t *res = NULL; + ComputeStatus rc = one_off("test.biom", "test.tre", + "weighted_normalized", true, 1.0, + false, 1, &res); + ASSERT(rc == okay); + double *expS = (double*)malloc(sizeof(double) * 18); + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + free(expS); + destroy_mat(&res); + SUITE_END(); } @@ -1524,6 +1673,22 @@ void test_unweighted_unifrac() { } free(strides[i]); } + + // repeat using the API + double* cstripes[] = {stride1, stride2, stride3}; + mat_t *res = NULL; + ComputeStatus rc = one_off("test.biom", "test.tre", + "unweighted", false, 0.0, + false, 1, &res); + ASSERT(rc == okay); + double *expS = (double*)malloc(sizeof(double) * 18); + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + free(expS); + destroy_mat(&res); + SUITE_END(); } @@ -1563,6 +1728,22 @@ void test_unweighted_unifrac_fast() { } free(strides[i]); } + + // repeat using the API + double* cstripes[] = {stride1, stride2, stride3}; + mat_t *res = NULL; + ComputeStatus rc = one_off("test.biom", "test.tre", + "unweighted", false, 0.0, + true, 1, &res); + ASSERT(rc == okay); + double *expS = (double*)malloc(sizeof(double) * 18); + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + free(expS); + destroy_mat(&res); + SUITE_END(); } @@ -1602,6 +1783,22 @@ void test_unnormalized_unweighted_unifrac() { } free(strides[i]); } + + // repeat using the API + double* cstripes[] = {stride1, stride2, stride3}; + mat_t *res = NULL; + ComputeStatus rc = one_off("test.biom", "test.tre", + "unweighted_unnormalized", false, 0.0, + false, 1, &res); + ASSERT(rc == okay); + double *expS = (double*)malloc(sizeof(double) * 18); + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + free(expS); + destroy_mat(&res); + SUITE_END(); } @@ -1642,6 +1839,22 @@ void test_normalized_weighted_unifrac() { } free(strides[i]); } + + // repeat using the API + double* cstripes[] = {stride1, stride2, stride3}; + mat_t *res = NULL; + ComputeStatus rc = one_off("test.biom", "test.tre", + "weighted_normalized", false, 0.0, + false, 1, &res); + ASSERT(rc == okay); + double *expS = (double*)malloc(sizeof(double) * 18); + _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); + for(unsigned int i = 0; i < 18; i++) { + ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); + } + free(expS); + destroy_mat(&res); + SUITE_END(); } From b45a9c70a1d8b4c1ce2e680720681bc848be1600 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 11:59:11 -0800 Subject: [PATCH 06/12] Add API-based faithpd tests in test_su --- src/test_faith.tre | 1 + src/test_faith_shear.tre | 1 + src/test_su.cpp | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+) create mode 100644 src/test_faith.tre create mode 100644 src/test_faith_shear.tre diff --git a/src/test_faith.tre b/src/test_faith.tre new file mode 100644 index 0000000..daf88d2 --- /dev/null +++ b/src/test_faith.tre @@ -0,0 +1 @@ +((GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1):2,(GG_OTU_5:1,GG_OTU_4:1):1); diff --git a/src/test_faith_shear.tre b/src/test_faith_shear.tre new file mode 100644 index 0000000..1579f09 --- /dev/null +++ b/src/test_faith_shear.tre @@ -0,0 +1 @@ +((GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1,GG_OTU_ex:9):1):2,(GG_OTU_5:1,GG_OTU_4:1,GG_OTU_ex2:12):1); diff --git a/src/test_su.cpp b/src/test_su.cpp index 054505e..e6e5796 100644 --- a/src/test_su.cpp +++ b/src/test_su.cpp @@ -1610,6 +1610,16 @@ void test_faith_pd() { for (unsigned int i = 0; i < 6; i++){ ASSERT(fabs(exp[i]-obs[i]) < 0.000001) } + + // repeat using the API + r_vec *res = NULL; + ComputeStatus rc = faith_pd_one_off("test.biom", "test_faith.tre", &res); + ASSERT(rc == okay); + for(unsigned int i = 0; i < 6; i++) { + ASSERT(fabs(res->values[i] - exp[i]) < 0.000001); + } + destroy_results_vec(&res); + SUITE_END(); } @@ -1634,6 +1644,16 @@ void test_faith_pd_shear(){ for (unsigned int i = 0; i < 6; i++){ ASSERT(fabs(exp[i]-obs[i]) < 0.000001) } + + // repeat using the API + r_vec *res = NULL; + ComputeStatus rc = faith_pd_one_off("test.biom", "test_faith_shear.tre", &res); + ASSERT(rc == okay); + for(unsigned int i = 0; i < 6; i++) { + ASSERT(fabs(res->values[i] - exp[i]) < 0.000001); + } + destroy_results_vec(&res); + SUITE_END(); } From ddceeee876c8a041249e39efc997f147dfbfc74f Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 12:36:47 -0800 Subject: [PATCH 07/12] Add test_su_api to exercise the optimiza code paths (test_su exercize the cpu-only internals) --- src/Makefile | 13 +++++++--- src/test_su.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index d919b29..d1c9b8d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -144,10 +144,14 @@ main: $(SSU) $(FPD) api: lib$(SSU).so -test_binaries: test_su test_ska test_api +test_binaries: test_su test_ska test_api test_su_api -test_su: test_su.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsampled.o unifrac.o skbio_alt.o api.o $(UNIFRAC_FILES) - $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_su.cpp -o test_su tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o skbio_alt.o api.o -llz4 $(BLASLIB) -lpthread +# first test the internal structures +test_su: test_su.cpp api.hpp tree.o tsv.o biom.o biom_inmem.o biom_subsampled.o unifrac.o skbio_alt.o api.o $(UNIFRAC_FILES) + $(CXX) $(CPPFLAGS) $(EXEFLAGS) test_su.cpp -o $@ tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o skbio_alt.o api.o -llz4 $(BLASLIB) -lpthread +# then exercise the optimized code through the API interface +test_su_api: test_su.cpp test_helper.hpp api.hpp $(PREFIX)/lib/lib$(SSU).so + $(CXX) $(CPPFLAGS) $(EXEFLAGS) -DAPI_ONLY=1 test_su.cpp -o $@ -l$(SSU) # Create an archive, so we do not need dependencies for functions we do not use test_ska_deps.a: tree.o tsv.o biom.o biom_inmem.o biom_subsampled.o skbio_alt.o api.o @@ -201,6 +205,7 @@ test: test_binaries ./test_su ./test_ska ./test_api + ./test_su_api install_lib: lib$(SSU).so rm -f ${PREFIX}/lib/lib$(SSU).so; cp lib$(SSU).so ${PREFIX}/lib/ @@ -233,5 +238,5 @@ rapi_test: tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o sk rm -f *.o clean: - -rm -f *.o $(SSU) $(FPD) *.a test_su test_ska test_api lib$(SSU).so unifrac_task_noclass.cpp + -rm -f *.o $(SSU) $(FPD) *.a test_su test_ska test_api test_su_api lib$(SSU).so unifrac_task_noclass.cpp diff --git a/src/test_su.cpp b/src/test_su.cpp index e6e5796..d549399 100644 --- a/src/test_su.cpp +++ b/src/test_su.cpp @@ -1,8 +1,12 @@ #include "api.hpp" + +#ifndef API_ONLY #include "tree.hpp" #include "biom.hpp" #include "unifrac.hpp" #include "unifrac_internal.hpp" +#endif + #include "test_helper.hpp" // copy of internal function in api... repeated here for testing @@ -52,6 +56,7 @@ void _testv_stripes_to_condensed_form(double* stripes[], uint32_t n, uint32_t m, } +#ifndef API_ONLY void test_bptree_simple_result(const su::BPTree &tree) { unsigned int exp_nparens = 8; @@ -874,6 +879,7 @@ void test_unifrac_deconvolute_stripes() { free(obs); SUITE_END(); } +#endif void test_unifrac_stripes_to_condensed_form_even() { SUITE_START("test stripes_to_condensed_form even samples"); @@ -901,12 +907,14 @@ void test_unifrac_stripes_to_condensed_form_even() { /* *, *, *, *, *, *, *, *, *, *, 0 */ double *obs = NULL; +#ifndef API_ONLY obs = (double*)malloc(sizeof(double) * 45); su::stripes_to_condensed_form(stripes, 10, obs, 0, 5); for(unsigned int i = 0; i < 45; i++) { ASSERT(exp[i] == obs[i]); } free(obs); +#endif // test internal version, too double* cstripes[] = {s1, s2, s3, s4 ,s5}; obs = (double*)malloc(sizeof(double) * 45); @@ -944,12 +952,14 @@ void test_unifrac_stripes_to_condensed_form_odd() { /*11, 30, 31, 50, 45, 35, 27, 13, 9, 0,*/ 10}; /* 0, 1, 2, 3, 4, 46, 34, 28, 12, 10, 0}; */ double *obs = NULL; +#ifndef API_ONLY obs = (double*)malloc(sizeof(double) * 55); su::stripes_to_condensed_form(stripes, 11, obs, 0, 5); for(unsigned int i = 0; i < 55; i++) { ASSERT(exp[i] == obs[i]); } free(obs); +#endif // test internal version, too double* cstripes[] = {s1, s2, s3, s4 ,s5}; obs = (double*)malloc(sizeof(double) * 55); @@ -985,12 +995,14 @@ void test_unifrac_stripes_to_condensed_form_odd2() { /*47, 42, 38, 24, 16, 6, 7, 0, */ 8}; /* 0, 1, 2, 3, 4, 46, 34, 8, 8, 0}; */ double *obs = NULL; +#ifndef API_ONLY obs = (double*)malloc(sizeof(double) * 36); su::stripes_to_condensed_form(stripes, 9, obs, 0, 5); for(unsigned int i = 0; i < 36; i++) { ASSERT(exp[i] == obs[i]); } free(obs); +#endif // test internal version, too double* cstripes[] = {s1, s2, s3, s4 ,s5}; obs = (double*)malloc(sizeof(double) * 36); @@ -1002,6 +1014,7 @@ void test_unifrac_stripes_to_condensed_form_odd2() { SUITE_END(); } +#ifndef API_ONLY class ValidatedMemoryStripes : public su::MemoryStripes { private: const uint32_t n_stripes; @@ -1296,19 +1309,23 @@ void test_unifrac_stripes_to_matrix_odd2() { free(obsC); SUITE_END(); } +#endif void test_unnormalized_weighted_unifrac() { SUITE_START("test unnormalized weighted unifrac"); +#ifndef API_ONLY std::vector threads(1); su::BPTree tree("(GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif std::vector exp; double stride1[] = {1.52380952, 1.25, 2.75, 1.33333333, 2., 1.07142857}; double stride2[] = {2.17857143, 2.66666667, 3.25, 1.0, 1.14285714, 1.83333333}; double stride3[] = {1.9047619, 2.66666667, 1.75, 1.9047619, 2.66666667, 1.75}; +#ifndef API_ONLY exp.push_back(stride1); exp.push_back(stride2); exp.push_back(stride3); @@ -1335,6 +1352,7 @@ void test_unnormalized_weighted_unifrac() { } free(strides[i]); } +#endif // repeat using the API double* cstripes[] = {stride1, stride2, stride3}; @@ -1357,15 +1375,18 @@ void test_unnormalized_weighted_unifrac() { void test_generalized_unifrac() { SUITE_START("test generalized unifrac"); +#ifndef API_ONLY std::vector threads(1); su::BPTree tree("(GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif // weighted normalized unifrac as computed above std::vector w_exp; double w_stride1[] = {0.38095238, 0.33333333, 0.73333333, 0.33333333, 0.5, 0.26785714}; double w_stride2[] = {0.58095238, 0.66666667, 0.86666667, 0.25, 0.28571429, 0.45833333}; double w_stride3[] = {0.47619048, 0.66666667, 0.46666667, 0.47619048, 0.66666667, 0.46666667}; +#ifndef API_ONLY w_exp.push_back(w_stride1); w_exp.push_back(w_stride2); w_exp.push_back(w_stride3); @@ -1385,6 +1406,7 @@ void test_generalized_unifrac() { std::ref(w_strides_total), std::ref(threads), std::ref(tasks)); +#endif // as computed by GUniFrac v1.0 // Sample1 Sample2 Sample3 Sample4 Sample5 Sample6 @@ -1398,6 +1420,7 @@ void test_generalized_unifrac() { double d0_stride1[] = {0.4408392, 0.5102041, 0.8649351, 0.5000000, 0.7485714, 0.3278410}; double d0_stride2[] = {0.6886965, 0.7500000, 0.9428571, 0.4857143, 0.5833333, 0.5208125}; double d0_stride3[] = {0.7060606, 0.8000000, 0.5952381, 0.7060606, 0.8000000, 0.5952381}; +#ifndef API_ONLY d0_exp.push_back(d0_stride1); d0_exp.push_back(d0_stride2); d0_exp.push_back(d0_stride3); @@ -1417,6 +1440,7 @@ void test_generalized_unifrac() { std::ref(d0_strides_total), std::ref(threads), std::ref(tasks)); +#endif // as computed by GUniFrac v1.0 // Sample1 Sample2 Sample3 Sample4 Sample5 Sample6 @@ -1430,6 +1454,7 @@ void test_generalized_unifrac() { double d05_stride1[] = {0.4040518, 0.4160597, 0.8005220, 0.4117216, 0.6188282, 0.2995673}; double d05_stride2[] = {0.6285560, 0.7071068, 0.9073159, 0.3485667, 0.4082483, 0.4860856}; double d05_stride3[] = {0.5869439, 0.7302479, 0.5218198, 0.5869439, 0.7302479, 0.5218198}; +#ifndef API_ONLY d05_exp.push_back(d05_stride1); d05_exp.push_back(d05_stride2); d05_exp.push_back(d05_stride3); @@ -1460,6 +1485,7 @@ void test_generalized_unifrac() { free(d0_strides[i]); free(d05_strides[i]); } +#endif // repeat using the API double* cstripes[3]; @@ -1509,9 +1535,11 @@ void test_generalized_unifrac() { void test_vaw_unifrac_weighted_normalized() { SUITE_START("test vaw weighted normalized unifrac"); +#ifndef API_ONLY std::vector threads(1); su::BPTree tree("(GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif // as computed by GUniFrac, the original implementation of VAW-UniFrac // could not be found. @@ -1528,6 +1556,7 @@ void test_vaw_unifrac_weighted_normalized() { double w_stride1[] = {0.4086040, 0.3798594, 0.7713254, 0.6666667, 0.4735991, 0.2766318}; double w_stride2[] = {0.6240185, 0.6884992, 0.8812897, 0.2709298, 0.2857143, 0.4735781}; double w_stride3[] = {0.4639481, 0.6807616, 0.5047114, 0.4639481, 0.6807616, 0.5047114}; +#ifndef API_ONLY w_exp.push_back(w_stride1); w_exp.push_back(w_stride2); w_exp.push_back(w_stride3); @@ -1554,6 +1583,7 @@ void test_vaw_unifrac_weighted_normalized() { } free(w_strides[i]); } +#endif // repeat using the API double* cstripes[] = {w_stride1, w_stride2, w_stride3}; @@ -1574,6 +1604,7 @@ void test_vaw_unifrac_weighted_normalized() { } +#ifndef API_ONLY void test_make_strides() { SUITE_START("test make stripes"); std::vector exp; @@ -1590,13 +1621,16 @@ void test_make_strides() { free(obs[i]); } } +#endif void test_faith_pd() { SUITE_START("test faith PD"); +#ifndef API_ONLY // Note this tree is binary (opposed to example below) su::BPTree tree("((GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1):2,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif // make vector of expectations from faith PD double exp[6] = {6., 7., 8., 5., 4., 7.}; @@ -1604,12 +1638,14 @@ void test_faith_pd() { // run faith PD to get obs double obs[6] = {0, 0, 0, 0, 0, 0}; +#ifndef API_ONLY su::faith_pd(table, tree, obs); // ASSERT that results = expectation for (unsigned int i = 0; i < 6; i++){ ASSERT(fabs(exp[i]-obs[i]) < 0.000001) } +#endif // repeat using the API r_vec *res = NULL; @@ -1626,8 +1662,10 @@ void test_faith_pd() { void test_faith_pd_shear(){ SUITE_START("test faith PD extra OTUs in tree"); +#ifndef API_ONLY su::BPTree tree("((GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1,GG_OTU_ex:9):1):2,(GG_OTU_5:1,GG_OTU_4:1,GG_OTU_ex2:12):1);"); su::biom table("test.biom"); +#endif // make vector of expectations from faith PD double exp[6] = {6., 7., 8., 5., 4., 7.}; @@ -1635,6 +1673,7 @@ void test_faith_pd_shear(){ // run faith PD to get obs double obs[6] = {0, 0, 0, 0, 0, 0}; +#ifndef API_ONLY std::unordered_set to_keep(table.get_obs_ids().begin(), \ table.get_obs_ids().end()); \ su::BPTree tree_sheared = tree.shear(to_keep).collapse(); @@ -1644,6 +1683,7 @@ void test_faith_pd_shear(){ for (unsigned int i = 0; i < 6; i++){ ASSERT(fabs(exp[i]-obs[i]) < 0.000001) } +#endif // repeat using the API r_vec *res = NULL; @@ -1659,14 +1699,17 @@ void test_faith_pd_shear(){ void test_unweighted_unifrac() { SUITE_START("test unweighted unifrac"); +#ifndef API_ONLY std::vector threads(1); su::BPTree tree("(GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif std::vector exp; double stride1[] = {0.2, 0.42857143, 0.71428571, 0.33333333, 0.6, 0.2}; double stride2[] = {0.57142857, 0.66666667, 0.85714286, 0.4, 0.5, 0.33333333}; double stride3[] = {0.6, 0.6, 0.42857143, 0.6, 0.6, 0.42857143}; +#ifndef API_ONLY exp.push_back(stride1); exp.push_back(stride2); exp.push_back(stride3); @@ -1693,6 +1736,7 @@ void test_unweighted_unifrac() { } free(strides[i]); } +#endif // repeat using the API double* cstripes[] = {stride1, stride2, stride3}; @@ -1714,14 +1758,17 @@ void test_unweighted_unifrac() { void test_unweighted_unifrac_fast() { SUITE_START("test unweighted unifrac no tips"); +#ifndef API_ONLY std::vector threads(1); su::BPTree tree("(GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif std::vector exp; double stride1[] = {0., 0., 0.5, 0., 0.5, 0.}; double stride2[] = {0., 0.5, 0.5, 0.5, 0.5, 0.}; double stride3[] = {0.5, 0.5, 0., 0.5, 0.5, 0.}; +#ifndef API_ONLY exp.push_back(stride1); exp.push_back(stride2); exp.push_back(stride3); @@ -1748,6 +1795,7 @@ void test_unweighted_unifrac_fast() { } free(strides[i]); } +#endif // repeat using the API double* cstripes[] = {stride1, stride2, stride3}; @@ -1769,14 +1817,17 @@ void test_unweighted_unifrac_fast() { void test_unnormalized_unweighted_unifrac() { SUITE_START("test unnormalized unweighted unifrac"); +#ifndef API_ONLY std::vector threads(1); su::BPTree tree("(GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif std::vector exp; double stride1[] = {1,3,5,1,3,1}; double stride2[] = {4,4,6,2,2,2}; double stride3[] = {3,3,3,3,3,3}; +#ifndef API_ONLY exp.push_back(stride1); exp.push_back(stride2); exp.push_back(stride3); @@ -1803,6 +1854,7 @@ void test_unnormalized_unweighted_unifrac() { } free(strides[i]); } +#endif // repeat using the API double* cstripes[] = {stride1, stride2, stride3}; @@ -1824,14 +1876,17 @@ void test_unnormalized_unweighted_unifrac() { void test_normalized_weighted_unifrac() { SUITE_START("test normalized weighted unifrac"); +#ifndef API_ONLY std::vector threads(1); su::BPTree tree("(GG_OTU_1:1,(GG_OTU_2:1,GG_OTU_3:1):1,(GG_OTU_5:1,GG_OTU_4:1):1);"); su::biom table("test.biom"); +#endif std::vector exp; double stride1[] = {0.38095238, 0.33333333, 0.73333333, 0.33333333, 0.5, 0.26785714}; double stride2[] = {0.58095238, 0.66666667, 0.86666667, 0.25, 0.28571429, 0.45833333}; double stride3[] = {0.47619048, 0.66666667, 0.46666667, 0.47619048, 0.66666667, 0.46666667}; +#ifndef API_ONLY exp.push_back(stride1); exp.push_back(stride2); exp.push_back(stride3); @@ -1859,6 +1914,7 @@ void test_normalized_weighted_unifrac() { } free(strides[i]); } +#endif // repeat using the API double* cstripes[] = {stride1, stride2, stride3}; @@ -1878,6 +1934,7 @@ void test_normalized_weighted_unifrac() { SUITE_END(); } +#ifndef API_ONLY void test_bptree_shear_simple() { SUITE_START("test bptree shear simple"); su::BPTree tree("((3:2,4:3,(6:5)5:4)2:1,7:6,((10:9,11:10)9:8)8:7)r"); @@ -2172,8 +2229,10 @@ void test_bptree_constructor_newline_bug() { su::BPTree tree("((362be41f31fd26be95ae43a8769b91c0:0.116350803,(a16679d5a10caa9753f171977552d920:0.105836235,((a7acc2abb505c3ee177a12e514d3b994:0.008268754,(4e22aa3508b98813f52e1a12ffdb74ad:0.03144211,8139c4ac825dae48454fb4800fb87896:0.043622957)0.923:0.046588301)0.997:0.120902074,((2d3df7387323e2edcbbfcb6e56a02710:0.031543994,3f6752aabcc291b67a063fb6492fd107:0.091571442)0.759:0.016335166,((d599ebe277afb0dfd4ad3c2176afc50e:5e-09,84d0affc7243c7d6261f3a7d680b873f:0.010245188)0.883:0.048993011,51121722488d0c3da1388d1b117cd239:0.119447926)0.763:0.035660204)0.921:0.058191474)0.776:0.02854575)0.657:0.052060833)0.658:0.032547569,(99647b51f775c8ddde8ed36a7d60dbcd:0.173334268,(f18a9c8112372e2916a66a9778f3741b:0.194813398,(5833416522de0cca717a1abf720079ac:5e-09,(2bf1067d2cd4f09671e3ebe5500205ca:0.031692682,(b32621bcd86cb99e846d8f6fee7c9ab8:0.031330707,1016319c25196d73bdb3096d86a9df2f:5e-09)0.058:0.01028612)0.849:0.010284866)0.791:0.041353384)0.922:0.109470534):0.022169824000000005)root;\n\n"); SUITE_END(); } +#endif int main(int argc, char** argv) { +#ifndef API_ONLY test_bptree_constructor_simple(); test_bptree_constructor_simple_cpp(); test_bptree_constructor_newline_bug(); @@ -2215,12 +2274,18 @@ int main(int argc, char** argv) { test_unifrac_set_proportions_range(); test_unifrac_set_proportions_range_float(); test_unifrac_deconvolute_stripes(); +#endif + test_unifrac_stripes_to_condensed_form_even(); test_unifrac_stripes_to_condensed_form_odd(); test_unifrac_stripes_to_condensed_form_odd2(); + +#ifndef API_ONLY test_unifrac_stripes_to_matrix_even(); test_unifrac_stripes_to_matrix_odd(); test_unifrac_stripes_to_matrix_odd2(); +#endif + test_unweighted_unifrac(); test_unweighted_unifrac_fast(); test_unnormalized_unweighted_unifrac(); @@ -2228,9 +2293,12 @@ int main(int argc, char** argv) { test_normalized_weighted_unifrac(); test_generalized_unifrac(); test_vaw_unifrac_weighted_normalized(); + +#ifndef API_ONLY test_unifrac_sample_counts(); test_set_tasks(); test_test_table_ids_are_subset_of_tree(); +#endif test_faith_pd(); test_faith_pd_shear(); From e53236eaa8cd1b01d642b3587bc610c58afe1ea5 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 13:20:28 -0800 Subject: [PATCH 08/12] Handle NOGPU at top-level Makefile, so nv not required --- Makefile | 46 +++++++++++++++++++++++++++++++++++++++------- combined/Makefile | 4 ++++ combined/libssu.c | 20 ++++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9028042..53fee16 100644 --- a/Makefile +++ b/Makefile @@ -6,20 +6,52 @@ PLATFORM := $(shell uname -s) COMPILER := $(shell ($(CXX) -v 2>&1) | tr A-Z a-z ) ifeq ($(PLATFORM),Darwin) -all: api install main install_main test_binaries +# no GPU support for MacOS +all: + make api + make install + make main + make install_main + make test_binaries else +# Linux with optional GPU support -# Note: important that all_nv is after all_cpu_basic and all_nv_avx2 for tests to work -all: all_cpu_basic all_nv_avx2 all_nv all_combined test_binaries +ifndef NOGPU -all_cpu_basic: api_cpu_basic install_cpu_basic +all: + make all_cpu_basic + make all_nv_avx2 + make all_nv + make all_combined + make test_binaries -all_nv: api_nv install_nv +else + +all: + make all_cpu_basic + make all_combined + make test_binaries + +endif + +all_cpu_basic: + make api_cpu_basic + make install_cpu_basic + +all_nv: + make api_nv + make install_nv -all_nv_avx2: api_nv_avx2 install_nv_avx2 +all_nv_avx2: + make api_nv_avx2 + make install_nv_avx2 -all_combined: api_combined install_combined main install_main +all_combined: + make api_combined + make install_combined + make main + make install_main endif diff --git a/combined/Makefile b/combined/Makefile index 3ca03f9..985ec87 100644 --- a/combined/Makefile +++ b/combined/Makefile @@ -12,6 +12,10 @@ ifeq ($(PREFIX),) PREFIX := $(CONDA_PREFIX) endif +ifdef NOGPU + CFLAGS += -DBASIC_ONLY +endif + libssu.o: libssu.c $(CC) $(CPPFLAGS) $(CFLAGS) -c libssu.c -fPIC diff --git a/combined/libssu.c b/combined/libssu.c index 26d9d1b..4a38785 100644 --- a/combined/libssu.c +++ b/combined/libssu.c @@ -26,6 +26,7 @@ static pthread_mutex_t dl_mutex = PTHREAD_MUTEX_INITIALIZER; /*********************************************************************/ /* Pick the right libssu implementation */ +#ifndef BASIC_ONLY static const char *ssu_get_lib_name() { __builtin_cpu_init (); bool has_avx = __builtin_cpu_supports ("avx"); @@ -63,6 +64,25 @@ static const char *ssu_get_lib_name() { return ssu; } +#else +static const char *ssu_get_lib_name() { + const char *ssu = "libssu_cpu_basic.so"; + + const char* env_gpu_info = getenv("UNIFRAC_GPU_INFO"); + if ((env_gpu_info!=NULL) && (env_gpu_info[0]=='Y')) { + printf("INFO (unifrac): No GPU support in this version\n"); + } + + const char* env_cpu_info = getenv("UNIFRAC_CPU_INFO"); + if ((env_cpu_info!=NULL) && (env_cpu_info[0]=='Y')) { + printf("INFO (unifrac): Using shared library %s\n",ssu); + } + return ssu; +} + + +#endif + /*********************************************************************/ /* Handle pointing to the approriate libssu implementing the functionality From ba82d8449dfcf64992354c59d6a1ff901c01cfbf Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 13:58:34 -0800 Subject: [PATCH 09/12] Add support for parallel make --- Makefile | 84 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index 53fee16..3817810 100644 --- a/Makefile +++ b/Makefile @@ -8,11 +8,11 @@ COMPILER := $(shell ($(CXX) -v 2>&1) | tr A-Z a-z ) ifeq ($(PLATFORM),Darwin) # no GPU support for MacOS all: - make api - make install - make main - make install_main - make test_binaries + $(MAKE) api + $(MAKE) install + $(MAKE) main + $(MAKE) install_main + $(MAKE) test_binaries else # Linux with optional GPU support @@ -20,95 +20,95 @@ else ifndef NOGPU all: - make all_cpu_basic - make all_nv_avx2 - make all_nv - make all_combined - make test_binaries + $(MAKE) all_cpu_basic + $(MAKE) all_nv_avx2 + $(MAKE) all_nv + $(MAKE) all_combined + $(MAKE) test_binaries else all: - make all_cpu_basic - make all_combined - make test_binaries + $(MAKE) all_cpu_basic + $(MAKE) all_combined + $(MAKE) test_binaries endif all_cpu_basic: - make api_cpu_basic - make install_cpu_basic + $(MAKE) api_cpu_basic + $(MAKE) install_cpu_basic all_nv: - make api_nv - make install_nv + $(MAKE) api_nv + $(MAKE) install_nv all_nv_avx2: - make api_nv_avx2 - make install_nv_avx2 + $(MAKE) api_nv_avx2 + $(MAKE) install_nv_avx2 all_combined: - make api_combined - make install_combined - make main - make install_main + $(MAKE) api_combined + $(MAKE) install_combined + $(MAKE) main + $(MAKE) install_main endif clean: - -cd test && make clean - -cd src && make clean - -cd combined && make clean + -cd test && $(MAKE) clean + -cd src && $(MAKE) clean + -cd combined && $(MAKE) clean ########### api api: - cd src && make clean && make api + cd src && $(MAKE) clean && $(MAKE) api api_cpu_basic: - export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make clean && make api + export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && $(MAKE) clean && $(MAKE) api api_nv: - . ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make clean && make api + . ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && $(MAKE) clean && $(MAKE) api api_nv_avx2: - . ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && make clean && make api + . ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && $(MAKE) clean && $(MAKE) api api_combined: - cd combined && make clean && make api + cd combined && $(MAKE) clean && $(MAKE) api ########### main main: - cd src && make clean && make main + cd src && $(MAKE) clean && $(MAKE) main install_main: - cd src && make install + cd src && $(MAKE) install ########### install install: - cd src && make install_lib + cd src && $(MAKE) install_lib install_cpu_basic: - export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make install_lib + export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && $(MAKE) install_lib install_nv: - . ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make install_lib + . ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && $(MAKE) install_lib install_nv_avx2: - . ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && make install_lib + . ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && $(MAKE) install_lib install_combined: - cd combined && make install + cd combined && $(MAKE) install ########### test test_binaries: - cd src && make clean && make test_binaries - cd test && make clean && make test_binaries + cd src && $(MAKE) clean && $(MAKE) test_binaries + cd test && $(MAKE) clean && $(MAKE) test_binaries test: - cd src && make test - cd test && make test + cd src && $(MAKE) test + cd test && $(MAKE) test From 267d158837bff20f59aea1c41c7b87fca36ac7d1 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 14:28:15 -0800 Subject: [PATCH 10/12] Add clean_install make option --- Makefile | 36 ++++++++++++++++++++++++++++++------ combined/Makefile | 7 +++++-- src/Makefile | 3 +++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 3817810..5611c5a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: test clean all +.PHONY: test clean all clean_install # Note: This Makefile will NOT properly work with the -j option @@ -14,6 +14,13 @@ all: $(MAKE) install_main $(MAKE) test_binaries +clean: + -cd test && $(MAKE) clean + -cd src && $(MAKE) clean + +clean_install: + -cd src && $(MAKE) clean_install + else # Linux with optional GPU support @@ -26,6 +33,19 @@ all: $(MAKE) all_combined $(MAKE) test_binaries +clean: + -cd test && $(MAKE) clean + -export BUILD_VARIANT=cpu_basic; cd src && $(MAKE) clean + -export BUILD_VARIANT=nv; cd src && $(MAKE) clean + -export BUILD_VARIANT=nv_avx2; cd src && $(MAKE) clean + -cd combined && $(MAKE) clean + +clean_install: + -export BUILD_VARIANT=cpu_basic; cd src && $(MAKE) clean_install + -export BUILD_VARIANT=nv; cd src && $(MAKE) clean_install + -export BUILD_VARIANT=nv_avx2; cd src && $(MAKE) clean_install + -cd combined && $(MAKE) clean_install + else all: @@ -33,6 +53,15 @@ all: $(MAKE) all_combined $(MAKE) test_binaries +clean: + -cd test && $(MAKE) clean + -export BUILD_VARIANT=cpu_basic; cd src && $(MAKE) clean + -cd combined && $(MAKE) clean + +clean_install: + -export BUILD_VARIANT=cpu_basic; cd src && $(MAKE) clean_install + -cd combined && $(MAKE) clean_install + endif all_cpu_basic: @@ -55,11 +84,6 @@ all_combined: endif -clean: - -cd test && $(MAKE) clean - -cd src && $(MAKE) clean - -cd combined && $(MAKE) clean - ########### api api: diff --git a/combined/Makefile b/combined/Makefile index 985ec87..7502eae 100644 --- a/combined/Makefile +++ b/combined/Makefile @@ -1,4 +1,4 @@ -.PHONY: all api main install clean +.PHONY: all api main install clean clean_install all: api install @@ -26,4 +26,7 @@ install: libssu.so rm -f ${PREFIX}/lib/libssu.so; cp libssu.so ${PREFIX}/lib/ clean: - rm -f libssu.o libssu.so + rm -f libssu.o + +clean_install: + rm -f ${PREFIX}/lib/libssu.so diff --git a/src/Makefile b/src/Makefile index d1c9b8d..9820969 100644 --- a/src/Makefile +++ b/src/Makefile @@ -240,3 +240,6 @@ rapi_test: tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o sk clean: -rm -f *.o $(SSU) $(FPD) *.a test_su test_ska test_api test_su_api lib$(SSU).so unifrac_task_noclass.cpp +clean_install: + -rm -f ${PREFIX}/lib/lib$(SSU).so ${PREFIX}/bin/$(SSU) ${PREFIX}/bin/$(FPD) ${PREFIX}/include/unifrac/task_parameters.hpp ${PREFIX}/include/unifrac/api.hpp ${PREFIX}/include/unifrac/status_enum.hpp + From 7c9c6ac358f5e07585c004e8e2be32ae4140caf9 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 16:19:35 -0800 Subject: [PATCH 11/12] Fix test_su_api checks --- src/test_su.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/test_su.cpp b/src/test_su.cpp index d549399..a6cfa54 100644 --- a/src/test_su.cpp +++ b/src/test_su.cpp @@ -1361,9 +1361,9 @@ void test_unnormalized_weighted_unifrac() { "weighted_unnormalized", false, 0.0, false, 1, &res); ASSERT(rc == okay); - double *expS = (double*)malloc(sizeof(double) * 18); + double *expS = (double*)malloc(sizeof(double) * 15); _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } free(expS); @@ -1489,7 +1489,7 @@ void test_generalized_unifrac() { // repeat using the API double* cstripes[3]; - double *expS = (double*)malloc(sizeof(double) * 18); + double *expS = (double*)malloc(sizeof(double) * 15); mat_t *res = NULL; ComputeStatus rc; @@ -1500,7 +1500,7 @@ void test_generalized_unifrac() { ASSERT(rc == okay); cstripes[0] = w_stride1; cstripes[1] = w_stride2; cstripes[2] = w_stride3; _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } destroy_mat(&res); @@ -1511,7 +1511,7 @@ void test_generalized_unifrac() { ASSERT(rc == okay); cstripes[0] = d0_stride1; cstripes[1] = d0_stride2; cstripes[2] = d0_stride3; _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } destroy_mat(&res); @@ -1522,7 +1522,7 @@ void test_generalized_unifrac() { ASSERT(rc == okay); cstripes[0] = d05_stride1; cstripes[1] = d05_stride2; cstripes[2] = d05_stride3; _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } destroy_mat(&res); @@ -1592,9 +1592,9 @@ void test_vaw_unifrac_weighted_normalized() { "weighted_normalized", true, 1.0, false, 1, &res); ASSERT(rc == okay); - double *expS = (double*)malloc(sizeof(double) * 18); + double *expS = (double*)malloc(sizeof(double) * 15); _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } free(expS); @@ -1745,9 +1745,9 @@ void test_unweighted_unifrac() { "unweighted", false, 0.0, false, 1, &res); ASSERT(rc == okay); - double *expS = (double*)malloc(sizeof(double) * 18); + double *expS = (double*)malloc(sizeof(double) * 15); _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } free(expS); @@ -1804,9 +1804,9 @@ void test_unweighted_unifrac_fast() { "unweighted", false, 0.0, true, 1, &res); ASSERT(rc == okay); - double *expS = (double*)malloc(sizeof(double) * 18); + double *expS = (double*)malloc(sizeof(double) * 15); _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } free(expS); @@ -1863,9 +1863,9 @@ void test_unnormalized_unweighted_unifrac() { "unweighted_unnormalized", false, 0.0, false, 1, &res); ASSERT(rc == okay); - double *expS = (double*)malloc(sizeof(double) * 18); + double *expS = (double*)malloc(sizeof(double) * 15); _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } free(expS); @@ -1923,9 +1923,9 @@ void test_normalized_weighted_unifrac() { "weighted_normalized", false, 0.0, false, 1, &res); ASSERT(rc == okay); - double *expS = (double*)malloc(sizeof(double) * 18); + double *expS = (double*)malloc(sizeof(double) * 15); _testv_stripes_to_condensed_form(cstripes, 6, 3, expS); - for(unsigned int i = 0; i < 18; i++) { + for(unsigned int i = 0; i < 15; i++) { ASSERT(fabs(res->condensed_form[i] - expS[i]) < 0.000001); } free(expS); From a74e67cb07c0b98b747cbaa1481780c1dd6114b7 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 24 Jan 2025 16:27:56 -0800 Subject: [PATCH 12/12] Add cpu-only builds --- .github/workflows/main.yml | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 86fc4ab..12b5557 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,14 +14,18 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-13, macos-14, linux-gpu-cuda] - offload: [acc, ompgpu] + offload: [cpu, acc, ompgpu] exclude: - - os: ubuntu-latest - offload: acc + - os: linux-gpu-cuda + offload: cpu - os: macos-14 offload: acc + - os: macos-14 + offload: ompgpu - os: macos-13 offload: acc + - os: macos-13 + offload: ompgpu runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -58,15 +62,20 @@ jobs: clang -v fi which h5c++ - if [[ "$(uname -s)" == "Linux" ]]; + export PERFORMING_CONDA_BUILD=True + export BUILD_OFFLOAD=${{ matrix.offload }} + if [[ "$(uname -s)" == "Linux" ]] && [[ "x${BUILD_OFFLOAD}" != "xcpu" ]]; then # install PGI but do not source it # the makefile will do it automatically ./scripts/install_hpc_sdk.sh