From 646b38cd95778f93a28834be707f66404b939176 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Thu, 4 May 2023 15:44:03 -0700 Subject: [PATCH 01/20] Add BUILD_VARIANT support to src/Makefle and first approximation of its use in Makefile --- Makefile | 68 +++++++++++++++++++++++++++++++++++++++++++++------- src/Makefile | 35 +++++++++++++++++---------- 2 files changed, 81 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index e070d01..54a108f 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,69 @@ -.PHONY: all main api test_binaries test install clean +.PHONY: all main api test_binaries test install clean all_combined all_basic all_gpu all_avx2 +ifeq ($(PLATFORM),Darwin) all: api main install -main: - cd src && make main +else +all: all_combined + +endif + +clean: + -cd test && make clean + -cd src && make clean + +all_combined: all_cpu_basic all_nv all_nv_avx2 + +all_cpu_basic: api_cpu_basic main_cpu_basic install_cpu_basic + +all_nv: api_nv main_nv install_nv + +all_nv_avx2: api_nv_avx2 main_nv_avx2 install_nv_avx2 + +########### api api: cd src && make api +api_cpu_basic: + export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make clean && make api + +api_nv: + source ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make clean && make api + +api_nv_avx2: + source ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && make clean && make api + +########### main + +main: + cd src && make main + +main_cpu_basic: + export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make main + +main_nv: + source ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make main + +main_nv_avx2: + source ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && make main + +########### install + +install: + cd src && make install + +install_cpu_basic: + export BUILD_VARIANT=cpu_basic ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make install + +install_nv: + source ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make install + +install_nv_avx2: + source ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && make install + +########### test + test_binaries: cd src && make test_binaries cd test && make test_binaries @@ -16,9 +72,3 @@ test: cd src && make test cd test && make test -install: - cd src && make install - -clean: - -cd test && make clean - -cd src && make clean diff --git a/src/Makefile b/src/Makefile index 1d5672b..43350db 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,6 +5,14 @@ CXX := h5c++ PLATFORM := $(shell uname -s) COMPILER := $(shell ($(CXX) -v 2>&1) | tr A-Z a-z ) +ifeq ($(BUILD_VARIANT),) + SSU = ssu + FPD = faithpd +else + SSU = ssu_$(BUILD_VARIANT) + FPD = faithpd_$(BUILD_VARIANT) +endif + ifdef DEBUG ifneq (,$(findstring pgi,$(COMPILER))) OPT = -g @@ -32,7 +40,7 @@ BLASLIB=-llapacke -lcblas ifeq ($(PLATFORM),Darwin) AVX2 := $(shell sysctl -a | grep -c AVX2) - LDDFLAGS = -dynamiclib -install_name @rpath/libssu.so + LDDFLAGS = -dynamiclib -install_name @rpath/lib$(SSU).so else AVX2 := $(shell grep "^flags" /proc/cpuinfo | head -n 1 | grep -c avx2) LDDFLAGS = -shared @@ -114,9 +122,9 @@ CPPFLAGS += -Wall -std=c++14 -pedantic -I. $(OPT) -fPIC -L$(PREFIX)/lib all: api main install -main: ssu faithpd +main: $(SSU) $(FPD) -api: libssu.so +api: lib$(SSU).so test_binaries: test_su test_ska test_api @@ -127,14 +135,14 @@ test_ska: test_ska.cpp tree.o tsv.o test_su.cpp biom.o biom_inmem.o biom_subsamp 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 -ssu: su.cpp tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o skbio_alt.o api.o $(UNIFRAC_FILES) - $(CXX) $(CPPFLAGS) $(EXEFLAGS) su.cpp -o ssu tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o cmd.o skbio_alt.o api.o -lhdf5_cpp -llz4 $(BLASLIB) -lpthread +$(SSU): su.cpp tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o skbio_alt.o api.o $(UNIFRAC_FILES) + $(CXX) $(CPPFLAGS) $(EXEFLAGS) su.cpp -o $(SSU) tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o cmd.o skbio_alt.o api.o -lhdf5_cpp -llz4 $(BLASLIB) -lpthread -faithpd: faithpd.cpp tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o skbio_alt.o api.o $(UNIFRAC_FILES) - $(CXX) $(CPPFLAGS) $(EXEFLAGS) faithpd.cpp -o faithpd tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o cmd.o skbio_alt.o api.o -lhdf5_cpp -llz4 $(BLASLIB) -lpthread +$(FPD): faithpd.cpp tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o skbio_alt.o api.o $(UNIFRAC_FILES) + $(CXX) $(CPPFLAGS) $(EXEFLAGS) faithpd.cpp -o $(FPD) tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o cmd.o skbio_alt.o api.o -lhdf5_cpp -llz4 $(BLASLIB) -lpthread -libssu.so: tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o skbio_alt.o api.o $(UNIFRAC_FILES) - $(CXX) $(LDDFLAGS) -o libssu.so tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o cmd.o skbio_alt.o api.o -lc -llz4 $(BLASLIB) -L$(PREFIX)/lib -noshlib -lhdf5_cpp -lhdf5_hl_cpp -lhdf5_hl -lhdf5 +lib$(SSU).so: tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o unifrac.o cmd.o skbio_alt.o api.o $(UNIFRAC_FILES) + $(CXX) $(LDDFLAGS) -o lib$(SSU).so tree.o biom.o biom_inmem.o biom_subsampled.o tsv.o $(UNIFRAC_FILES) unifrac.o cmd.o skbio_alt.o api.o -lc -llz4 $(BLASLIB) -L$(PREFIX)/lib -noshlib -lhdf5_cpp -lhdf5_hl_cpp -lhdf5_hl -lhdf5 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 @@ -153,9 +161,10 @@ test: test_binaries ./test_ska ./test_api -install: libssu.so ssu faithpd - cp libssu.so ${PREFIX}/lib/ - cp ssu faithpd ${PREFIX}/bin/ +install: lib$(SSU).so $(FPD) + cp lib$(SSU).so ${PREFIX}/lib/ + cp $(SSU) ${PREFIX}/bin/ + cp $(FPD) ${PREFIX}/bin/ mkdir -p ${PREFIX}/include/unifrac cp task_parameters.hpp ${PREFIX}/include/unifrac/ cp api.hpp ${PREFIX}/include/unifrac/ @@ -180,5 +189,5 @@ rapi_test: main rm -f *.o clean: - -rm -f *.o ssu faithpd test_su test_ska test_api libssu.so + -rm -f *.o $(SSU) $(FPD) test_su test_ska test_api lib$(SSU).so From c2406e8a77684e3873e14e8703290cb48a43b1a1 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Thu, 4 May 2023 17:12:48 -0700 Subject: [PATCH 02/20] Minor Makefile tweaks --- Makefile | 2 ++ src/Makefile | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 54a108f..c31eb2e 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,8 @@ clean: -cd test && make clean -cd src && make clean +########### all + all_combined: all_cpu_basic all_nv all_nv_avx2 all_cpu_basic: api_cpu_basic main_cpu_basic install_cpu_basic diff --git a/src/Makefile b/src/Makefile index 43350db..3b6a187 100644 --- a/src/Makefile +++ b/src/Makefile @@ -161,14 +161,14 @@ test: test_binaries ./test_ska ./test_api -install: lib$(SSU).so $(FPD) - cp lib$(SSU).so ${PREFIX}/lib/ - cp $(SSU) ${PREFIX}/bin/ - cp $(FPD) ${PREFIX}/bin/ +install: lib$(SSU).so $(SSU) $(FPD) + rm -f ${PREFIX}/lib//lib$(SSU).so; cp lib$(SSU).so ${PREFIX}/lib/ + rm -f ${PREFIX}/bin/$(SSU); cp $(SSU) ${PREFIX}/bin/ + rm -f ${PREFIX}/bin/$(FPD); cp $(FPD) ${PREFIX}/bin/ mkdir -p ${PREFIX}/include/unifrac - cp task_parameters.hpp ${PREFIX}/include/unifrac/ - cp api.hpp ${PREFIX}/include/unifrac/ - cp status_enum.hpp ${PREFIX}/include/unifrac/ + rm -f ${PREFIX}/include/unifrac/task_parameters.hpp; cp task_parameters.hpp ${PREFIX}/include/unifrac/ + rm -f ${PREFIX}/include/unifrac/api.hpp; cp api.hpp ${PREFIX}/include/unifrac/ + rm -f ${PREFIX}/include/unifrac/status_enum.hpp; cp status_enum.hpp ${PREFIX}/include/unifrac/ rapi_test: main mkdir -p ~/.R From ff65c570d5bee2282216a2ca8427868d023e3528 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 5 May 2023 14:03:17 -0700 Subject: [PATCH 03/20] Add ssu and faithpd multi-cpu wrappers and document UNIFRAC_MAX_CPU --- README.md | 7 +++++++ combined/faithpd | 40 ++++++++++++++++++++++++++++++++++++++++ combined/ssu | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100755 combined/faithpd create mode 100755 combined/ssu diff --git a/README.md b/README.md index 7ef0d28..65a5323 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,13 @@ To restrict the number of cores used, set: export OMP_NUM_THREADS=nthreads +## Older CPU support + +On Linux platforms, Unifrac will auto-detect the CPU generation, i.e. if it supports avx or avx2 vector instructions. +To force the most compatible binary variant, one can set: + + export UNIFRAC_MAX_CPU=basic + ## GPU support On Linux platforms, Unifrac will run on a GPU, if one is found. diff --git a/combined/faithpd b/combined/faithpd new file mode 100755 index 0000000..f3ee5e2 --- /dev/null +++ b/combined/faithpd @@ -0,0 +1,40 @@ +#!/bin/bash + +#default +FPD=faithpd_nv + +# Need at least AVX to support GPUs +if [ "${UNIFRAC_MAX_CPU}" == "basic" ]; then + has_no_avx=1 +else + cat /proc/cpuinfo |grep flags |head -1 | grep -q avx + has_no_avx=$? +fi + +if [ "${has_no_avx}" -eq 1 ]; then + FPD=faithpd_cpu_basic +else + +if [ "${UNIFRAC_MAX_CPU}" == "avx" ]; then + has_no_avx2=1 +else + cat /proc/cpuinfo |grep flags |head -1 | grep -q avx2 + has_no_avx2=$? +fi + +if [ "${has_no_avx2}" -eq 1 ]; then + FPD=faithpd_nv +else + FPD=faithpd_nv_avx2 +fi # if "${has_no_avx2}" -eq 1 + + +fi # if "${has_no_avx}" -eq 1 + +# +# +# +BASEDIR=$(dirname "$0") + +exec ${BASEDIR}/${FPD} "$@" + diff --git a/combined/ssu b/combined/ssu new file mode 100755 index 0000000..25e7060 --- /dev/null +++ b/combined/ssu @@ -0,0 +1,43 @@ +#!/bin/bash + +#default +SSU=ssu_nv + +# Need at least AVX to support GPUs +if [ "${UNIFRAC_MAX_CPU}" == "basic" ]; then + has_no_avx=1 +else + cat /proc/cpuinfo |grep flags |head -1 | grep -q avx + has_no_avx=$? +fi + +if [ "${has_no_avx}" -eq 1 ]; then + if [ "${UNIFRAC_GPU_INFO}" == "Y" ]; then + echo "INFO (unifrac): CPU too old, disabling GPU" + fi + SSU=ssu_cpu_basic +else + +if [ "${UNIFRAC_MAX_CPU}" == "avx" ]; then + has_no_avx2=1 +else + cat /proc/cpuinfo |grep flags |head -1 | grep -q avx2 + has_no_avx2=$? +fi + +if [ "${has_no_avx2}" -eq 1 ]; then + SSU=ssu_nv +else + SSU=ssu_nv_avx2 +fi # if "${has_no_avx2}" -eq 1 + + +fi # if "${has_no_avx}" -eq 1 + +# +# +# +BASEDIR=$(dirname "$0") + +exec ${BASEDIR}/${SSU} "$@" + From 80bcda35c07cfd68c5ff8bcbdcf38a38c80ed509 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 5 May 2023 15:35:02 -0700 Subject: [PATCH 04/20] Fix typo --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 3b6a187..f202e20 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -.PHONY: all make api test test_binaries install clean rapi_test +.PHONY: all main api test test_binaries install clean rapi_test CXX := h5c++ From e8a4090008985cd617b4d0b9b68f4c3c895e11fe Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 5 May 2023 15:36:56 -0700 Subject: [PATCH 05/20] Add combined. libssu.c and Makefile --- combined/Makefile | 23 +++++++++++++++++ combined/libssu.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 combined/Makefile create mode 100644 combined/libssu.c diff --git a/combined/Makefile b/combined/Makefile new file mode 100644 index 0000000..21ecb1e --- /dev/null +++ b/combined/Makefile @@ -0,0 +1,23 @@ +.PHONY: all main install clean + +all: main install + +main: libssu.so + + +ifeq ($(PREFIX),) + PREFIX := $(CONDA_PREFIX) +endif + +libssu.o: libssu.c + $(CC) -c libssu.c -fPIC + +libssu.so: libssu.o + $(CC) -shared -o libssu.so libssu.o -fPIC -ldl + +install: libssu.so + rm -f ${PREFIX}/lib//libssu.so; cp libssu.so ${PREFIX}/lib/ + rm -f ${PREFIX}/bin/ssu; cp ssu ${PREFIX}/bin/ + +clean: + rm -f libssu.o libssu.so diff --git a/combined/libssu.c b/combined/libssu.c new file mode 100644 index 0000000..b0c1ddb --- /dev/null +++ b/combined/libssu.c @@ -0,0 +1,65 @@ +#include +#include +#include + +#include "../src/api.hpp" + +static void *dl_handle = NULL; + +static const char *ssu_get_lib_name() { + /* + * TODO: Auto-detect appropriate CPU architecture + */ + return "libssu_nv.so"; +} + + +static void ssu_load(const char *fncname, + void **dl_ptr) { + char *error; + + if (dl_handle==NULL) { + dl_handle = dlopen(ssu_get_lib_name(), RTLD_LAZY); + if (!dl_handle) { + fputs(dlerror(), stderr); + exit(1); + } + } + + *dl_ptr = dlsym(dl_handle, fncname); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(1); + } +} + +/*********************************************************************/ + +static void (*dl_ssu_set_random_seed)(unsigned int) = NULL; +void ssu_set_random_seed(unsigned int new_seed) { + if (dl_ssu_set_random_seed==NULL) ssu_load("ssu_set_random_seed", (void **) &dl_ssu_set_random_seed); + + (*dl_ssu_set_random_seed)(new_seed); +} + +/*********************************************************************/ + +static ComputeStatus (*dl_one_off)(const char*, const char*, const char*, bool, double, bool, unsigned int, mat_t**) = NULL; +ComputeStatus one_off(const char* biom_filename, const char* tree_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, mat_t** result) { + if (dl_one_off==NULL) ssu_load("one_off", (void **) &dl_one_off); + + (*dl_one_off)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); +} + +/*********************************************************************/ + +static ComputeStatus (*dl_faith_pd_one_off)(const char*, const char*, r_vec**); +ComputeStatus faith_pd_one_off(const char* biom_filename, const char* tree_filename, + r_vec** result) { + if (dl_faith_pd_one_off==NULL) ssu_load("faith_pd_one_off", (void **) &dl_faith_pd_one_off); + + (*dl_faith_pd_one_off)(biom_filename, tree_filename, result); +} + From 8d43dd522eff2cccf40a60c045c354768ae1251e Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 5 May 2023 15:40:50 -0700 Subject: [PATCH 06/20] Revert build changes --- test/Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/Makefile b/test/Makefile index 539161d..14f79a3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -7,11 +7,6 @@ ifeq ($(PREFIX),) PREFIX := $(CONDA_PREFIX) endif -ifneq ($(PLATFORM),Darwin) - CC := gcc - LD := ld -endif - test: capi_test ./capi_test 1 From 64e9380e61b94916c97cca2b600b3fe46182a565 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 5 May 2023 16:18:32 -0700 Subject: [PATCH 07/20] Add CPU detection to libssu and add support for UNIFRAC_CPU_INFO --- README.md | 4 ++++ combined/Makefile | 1 + combined/faithpd | 4 ++++ combined/libssu.c | 37 ++++++++++++++++++++++++++++++++++++- combined/ssu | 4 ++++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 65a5323..7b64bed 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,10 @@ To force the most compatible binary variant, one can set: export UNIFRAC_MAX_CPU=basic +To check which binary is used (Unifrac will print it to standard output at runtime), set: + + export UNIFRAC_CPU_INFO=Y + ## GPU support On Linux platforms, Unifrac will run on a GPU, if one is found. diff --git a/combined/Makefile b/combined/Makefile index 21ecb1e..533b2e4 100644 --- a/combined/Makefile +++ b/combined/Makefile @@ -18,6 +18,7 @@ libssu.so: libssu.o install: libssu.so rm -f ${PREFIX}/lib//libssu.so; cp libssu.so ${PREFIX}/lib/ rm -f ${PREFIX}/bin/ssu; cp ssu ${PREFIX}/bin/ + rm -f ${PREFIX}/bin/faithpd; cp faithpd ${PREFIX}/bin/ clean: rm -f libssu.o libssu.so diff --git a/combined/faithpd b/combined/faithpd index f3ee5e2..b6bbf48 100755 --- a/combined/faithpd +++ b/combined/faithpd @@ -31,6 +31,10 @@ fi # if "${has_no_avx2}" -eq 1 fi # if "${has_no_avx}" -eq 1 +if [ "${UNIFRAC_CPU_INFO}" == "Y" ]; then + echo "INFO (unifrac): Using executable" ${FPD} +fi + # # # diff --git a/combined/libssu.c b/combined/libssu.c index b0c1ddb..dfa2e86 100644 --- a/combined/libssu.c +++ b/combined/libssu.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "../src/api.hpp" @@ -10,7 +11,41 @@ static const char *ssu_get_lib_name() { /* * TODO: Auto-detect appropriate CPU architecture */ - return "libssu_nv.so"; + + __builtin_cpu_init (); + bool has_avx = __builtin_cpu_supports ("avx"); + bool has_avx2 = __builtin_cpu_supports ("avx2"); + + const char* env_max_cpu = getenv("UNIFRAC_MAX_CPU"); + + if ((env_max_cpu!=NULL) && (strcmp(env_max_cpu,"basic")==0)) { + has_avx = false; + has_avx2 = false; + } + + const char *ssu = "libssu_nv.so"; + if (has_avx) { + if ((env_max_cpu!=NULL) && (strcmp(env_max_cpu,"avx")==0)) { + has_avx2 = false; + } + if (has_avx2) { + ssu="libssu_nv_avx2.so"; + } else { + ssu="libssu_nv.so"; + } + } else { // no avx + const char* env_gpu_info = getenv("UNIFRAC_GPU_INFO"); + if ((env_gpu_info!=NULL) && (env_gpu_info[0]=='Y')) { + printf("INFO (unifrac): CPU too old, disabling GPU\n"); + } + ssu="libssu_cpu_basic.so"; + } + + 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; } diff --git a/combined/ssu b/combined/ssu index 25e7060..1e8f8b1 100755 --- a/combined/ssu +++ b/combined/ssu @@ -34,6 +34,10 @@ fi # if "${has_no_avx2}" -eq 1 fi # if "${has_no_avx}" -eq 1 +if [ "${UNIFRAC_CPU_INFO}" == "Y" ]; then + echo "INFO (unifrac): Using executable" ${SSU} +fi + # # # From 001a751568d7e0417f8c63fb85787018aac8f28f Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Fri, 5 May 2023 16:19:29 -0700 Subject: [PATCH 08/20] Remove obsolete comment --- combined/libssu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/combined/libssu.c b/combined/libssu.c index dfa2e86..5159306 100644 --- a/combined/libssu.c +++ b/combined/libssu.c @@ -8,10 +8,6 @@ static void *dl_handle = NULL; static const char *ssu_get_lib_name() { - /* - * TODO: Auto-detect appropriate CPU architecture - */ - __builtin_cpu_init (); bool has_avx = __builtin_cpu_supports ("avx"); bool has_avx2 = __builtin_cpu_supports ("avx2"); From db531c2581b9cd5793fd83e67f7e15275bcd46c0 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 12:02:42 -0700 Subject: [PATCH 09/20] Add wrappers for destroy_ and one_off_inmem_ functions --- combined/libssu.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++- src/api.hpp | 8 ++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/combined/libssu.c b/combined/libssu.c index 5159306..8377b68 100644 --- a/combined/libssu.c +++ b/combined/libssu.c @@ -75,6 +75,51 @@ void ssu_set_random_seed(unsigned int new_seed) { /*********************************************************************/ +static void (*dl_destroy_mat)(mat_t**) = NULL; +static void (*dl_destroy_mat_full_fp64)(mat_full_fp64_t**) = NULL; +static void (*dl_destroy_mat_full_fp32)(mat_full_fp32_t**) = NULL; +static void (*dl_destroy_partial_mat)(partial_mat_t**) = NULL; +static void (*dl_destroy_partial_dyn_mat)(partial_dyn_mat_t**) = NULL; +static void (*dl_destroy_results_vec)(r_vec**) = NULL; + +void destroy_mat(mat_t** result) { + if (dl_destroy_mat==NULL) ssu_load("destroy_mat", (void **) &dl_destroy_mat); + + (*dl_destroy_mat)(result); +} + +void destroy_mat_full_fp64(mat_full_fp64_t** result) { + if (dl_destroy_mat_full_fp64==NULL) ssu_load("destroy_mat_full_fp64", (void **) &dl_destroy_mat_full_fp64); + + (*dl_destroy_mat_full_fp64)(result); +} + +void destroy_mat_full_fp32(mat_full_fp32_t** result) { + if (dl_destroy_mat_full_fp32==NULL) ssu_load("destroy_mat_full_fp32", (void **) &dl_destroy_mat_full_fp32); + + (*dl_destroy_mat_full_fp32)(result); +} + +void destroy_partial_mat(partial_mat_t** result) { + if (dl_destroy_partial_mat==NULL) ssu_load("destroy_partial_mat", (void **) &dl_destroy_partial_mat); + + (*dl_destroy_partial_mat)(result); +} + +void destroy_partial_dyn_mat(partial_dyn_mat_t** result) { + if (dl_destroy_partial_dyn_mat==NULL) ssu_load("destroy_partial_dyn_mat", (void **) &dl_destroy_partial_dyn_mat); + + (*dl_destroy_partial_dyn_mat)(result); +} + +void destroy_results_vec(r_vec** result) { + if (dl_destroy_results_vec==NULL) ssu_load("destroy_results_vec", (void **) &dl_destroy_results_vec); + + (*dl_destroy_results_vec)(result); +} + +/*********************************************************************/ + static ComputeStatus (*dl_one_off)(const char*, const char*, const char*, bool, double, bool, unsigned int, mat_t**) = NULL; ComputeStatus one_off(const char* biom_filename, const char* tree_filename, const char* unifrac_method, bool variance_adjust, double alpha, @@ -86,7 +131,56 @@ ComputeStatus one_off(const char* biom_filename, const char* tree_filename, /*********************************************************************/ -static ComputeStatus (*dl_faith_pd_one_off)(const char*, const char*, r_vec**); +static ComputeStatus (*dl_one_off_matrix_inmem_v2)(const support_biom_t *, const support_bptree_t *, const char*, bool, double, + bool, unsigned int, unsigned int, bool, const char *, mat_full_fp64_t**) = NULL; +static ComputeStatus (*dl_one_off_inmem)(const support_biom_t *, const support_bptree_t *, const char*, bool, double, + bool, unsigned int, mat_full_fp64_t**) = NULL; +static ComputeStatus (*dl_one_off_matrix_inmem_fp32_v2)(const support_biom_t *, const support_bptree_t *, const char*, bool, double, + bool, unsigned int, unsigned int, bool, const char *, mat_full_fp32_t**) = NULL; +static ComputeStatus (*dl_one_off_inmem_fp32)(const support_biom_t *, const support_bptree_t *, const char*, bool, double, + bool, unsigned int, mat_full_fp32_t**) = NULL; + +ComputeStatus one_off_matrix_inmem_v2(const support_biom_t *table_data, const support_bptree_t *tree_data, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, + unsigned int subsample_depth, bool subsample_with_replacement, const char *mmap_dir, + mat_full_fp64_t** result) { + if (dl_one_off_matrix_inmem_v2==NULL) ssu_load("one_off_matrix_inmem_v2", (void **) &dl_one_off_matrix_inmem_v2); + + (*dl_one_off_matrix_inmem_v2)(table_data, tree_data, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); +} + +ComputeStatus one_off_inmem(const support_biom_t *table_data, const support_bptree_t *tree_data, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, mat_full_fp64_t** result) { + if (dl_one_off_inmem==NULL) ssu_load("one_off_inmem", (void **) &dl_one_off_inmem); + + (*dl_one_off_inmem)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); +} + +ComputeStatus one_off_matrix_inmem_fp32_v2(const support_biom_t *table_data, const support_bptree_t *tree_data, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, + unsigned int subsample_depth, bool subsample_with_replacement, const char *mmap_dir, + mat_full_fp32_t** result) { + if (dl_one_off_matrix_inmem_fp32_v2==NULL) ssu_load("one_off_matrix_inmem_fp32_v2", (void **) &dl_one_off_matrix_inmem_fp32_v2); + + (*dl_one_off_matrix_inmem_fp32_v2)(table_data, tree_data, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); +} + +ComputeStatus one_off_inmem_fp32(const support_biom_t *table_data, const support_bptree_t *tree_data, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, mat_full_fp32_t** result) { + if (dl_one_off_inmem_fp32==NULL) ssu_load("one_off_inmem_fp32", (void **) &dl_one_off_inmem_fp32); + + (*dl_one_off_inmem_fp32)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); +} + +/*********************************************************************/ + +static ComputeStatus (*dl_faith_pd_one_off)(const char*, const char*, r_vec**) = NULL; ComputeStatus faith_pd_one_off(const char* biom_filename, const char* tree_filename, r_vec** result) { if (dl_faith_pd_one_off==NULL) ssu_load("faith_pd_one_off", (void **) &dl_faith_pd_one_off); diff --git a/src/api.hpp b/src/api.hpp index 2f2b899..44c40f8 100644 --- a/src/api.hpp +++ b/src/api.hpp @@ -11,6 +11,14 @@ #define EXTERN #endif +/* + * + * Note: Each function declared EXTERN must both have + * an implementation in api.cpp, AND + * a wrapper in ../combined/libssu.c + * + */ + #define PARTIAL_MAGIC "SSU-PARTIAL-01" #define PARTIAL_MAGIC_V2 0x088ABA02 From d8cf6b227493088768b3fb538f61ae4687339224 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 12:49:00 -0700 Subject: [PATCH 10/20] Add one_off_matrix_ , unifrac_to_file and compute_permanova_ functions --- combined/libssu.c | 154 +++++++++++++++++++++++++++++++++++++++++++++- src/api.hpp | 2 +- 2 files changed, 154 insertions(+), 2 deletions(-) diff --git a/combined/libssu.c b/combined/libssu.c index 8377b68..19485a9 100644 --- a/combined/libssu.c +++ b/combined/libssu.c @@ -1,3 +1,12 @@ +/* + * BSD 3-Clause License + * + * Copyright (c) 2023, UniFrac development team. + * All rights reserved. + * + * See LICENSE file for more details + */ + #include #include #include @@ -5,8 +14,15 @@ #include "../src/api.hpp" -static void *dl_handle = NULL; +/* + * Implement wrappers around all the EXTERN functions + * defined in api.hpp. + * + */ + +/*********************************************************************/ +/* Pick the right libssu implementation */ static const char *ssu_get_lib_name() { __builtin_cpu_init (); bool has_avx = __builtin_cpu_supports ("avx"); @@ -44,6 +60,11 @@ static const char *ssu_get_lib_name() { return ssu; } +/*********************************************************************/ + +/* Handle pointing to the approriate libssu implementing the functionality + * Initialized on first use. */ +static void *dl_handle = NULL; static void ssu_load(const char *fncname, void **dl_ptr) { @@ -65,6 +86,10 @@ static void ssu_load(const char *fncname, } /*********************************************************************/ +/* All the functons below are wrappers + * and each has its own function pointer + * that is initialized on first use */ +/*********************************************************************/ static void (*dl_ssu_set_random_seed)(unsigned int) = NULL; void ssu_set_random_seed(unsigned int new_seed) { @@ -180,6 +205,61 @@ ComputeStatus one_off_inmem_fp32(const support_biom_t *table_data, const support /*********************************************************************/ +static ComputeStatus (*dl_one_off_matrix_v2)(const char*, const char*, const char*, bool, double, + bool, unsigned int, unsigned int, bool, const char *, mat_full_fp64_t**) = NULL; +static ComputeStatus (*dl_one_off_matrix)(const char*, const char*, const char*, bool, double, + bool, unsigned int, const char *, mat_full_fp64_t**) = NULL; +static ComputeStatus (*dl_one_off_matrix_fp32_v2)(const char*, const char*, const char*, bool, double, + bool, unsigned int, unsigned int, bool, const char *, mat_full_fp32_t**) = NULL; +static ComputeStatus (*dl_one_off_matrix_fp32)(const char*, const char*, const char*, bool, double, + bool, unsigned int, const char *, mat_full_fp32_t**) = NULL; + +ComputeStatus one_off_matrix_v2(const char* biom_filename, const char* tree_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, + unsigned int subsample_depth, bool subsample_with_replacement, const char *mmap_dir, + mat_full_fp64_t** result) { + if (dl_one_off_matrix_v2==NULL) ssu_load("one_off_matrix_v2", (void **) &dl_one_off_matrix_v2); + + (*dl_one_off_matrix_v2)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); +} + +ComputeStatus one_off_matrix(const char* biom_filename, const char* tree_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, + const char *mmap_dir, + mat_full_fp64_t** result) { + if (dl_one_off_matrix==NULL) ssu_load("one_off_matrix", (void **) &dl_one_off_matrix); + + (*dl_one_off_matrix)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, mmap_dir, result); +} + +ComputeStatus one_off_matrix_fp32_v2(const char* biom_filename, const char* tree_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, + unsigned int subsample_depth, bool subsample_with_replacement, const char *mmap_dir, + mat_full_fp32_t** result) { + if (dl_one_off_matrix_fp32_v2==NULL) ssu_load("one_off_matrix_fp32_v2", (void **) &dl_one_off_matrix_fp32_v2); + + (*dl_one_off_matrix_fp32_v2)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); +} + +ComputeStatus one_off_matrix_fp32(const char* biom_filename, const char* tree_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, + const char *mmap_dir, + mat_full_fp32_t** result) { + if (dl_one_off_matrix_fp32==NULL) ssu_load("one_off_matrix_fp32", (void **) &dl_one_off_matrix_fp32); + + (*dl_one_off_matrix_fp32)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, mmap_dir, result); +} + +/*********************************************************************/ + static ComputeStatus (*dl_faith_pd_one_off)(const char*, const char*, r_vec**) = NULL; ComputeStatus faith_pd_one_off(const char* biom_filename, const char* tree_filename, r_vec** result) { @@ -188,3 +268,75 @@ ComputeStatus faith_pd_one_off(const char* biom_filename, const char* tree_filen (*dl_faith_pd_one_off)(biom_filename, tree_filename, result); } +/*********************************************************************/ + +static ComputeStatus (*dl_unifrac_to_file_v2)(const char*, const char*, const char*, const char*, bool, double, + bool, unsigned int, const char*, unsigned int, bool, + unsigned int, unsigned int, const char *, const char *, const char *) = NULL; +static ComputeStatus (*dl_unifrac_to_file)(const char*, const char*, const char*, const char*, bool, double, + bool, unsigned int, const char*, unsigned int, const char *) = NULL; +static ComputeStatus (*dl_unifrac_multi_to_file_v2)(const char*, const char*, const char*, const char*, bool, double, + bool, unsigned int, const char*, unsigned int, unsigned int, bool, + unsigned int, unsigned int, const char *, const char *, const char *) = NULL; + +ComputeStatus unifrac_to_file_v2(const char* biom_filename, const char* tree_filename, const char* out_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, const char* format, + unsigned int subsample_depth, bool subsample_with_replacement, + unsigned int pcoa_dims, + unsigned int permanova_perms, const char *grouping_filename, const char *grouping_columns, + const char *mmap_dir){ + if (dl_unifrac_to_file_v2==NULL) ssu_load("unifrac_to_file_v2", (void **) &dl_unifrac_to_file_v2); + + (*dl_unifrac_to_file_v2)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, format, subsample_depth, subsample_with_replacement, + pcoa_dims, permanova_perms, grouping_filename, grouping_columns, mmap_dir); +} + +ComputeStatus unifrac_to_file(const char* biom_filename, const char* tree_filename, const char* out_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, const char* format, + unsigned int pcoa_dims, const char *mmap_dir) { + if (dl_unifrac_to_file==NULL) ssu_load("unifrac_to_file", (void **) &dl_unifrac_to_file); + + (*dl_unifrac_to_file)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, format, pcoa_dims, mmap_dir); +} + +ComputeStatus unifrac_multi_to_file_v2(const char* biom_filename, const char* tree_filename, const char* out_filename, + const char* unifrac_method, bool variance_adjust, double alpha, + bool bypass_tips, unsigned int n_substeps, const char* format, + unsigned int n_subsamples, unsigned int subsample_depth, bool subsample_with_replacement, + unsigned int pcoa_dims, + unsigned int permanova_perms, const char *grouping_filename, const char *grouping_columns, + const char *mmap_dir) { + if (dl_unifrac_multi_to_file_v2==NULL) ssu_load("unifrac_multi_to_file_v2", (void **) &dl_unifrac_multi_to_file_v2); + + (*dl_unifrac_multi_to_file_v2)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, + bypass_tips, n_substeps, format, n_subsamples, subsample_depth, subsample_with_replacement, + pcoa_dims, permanova_perms, grouping_filename, grouping_columns, mmap_dir); +} + + +/*********************************************************************/ + +static ComputeStatus (*dl_compute_permanova_fp64)(const char *, unsigned int, const char**, mat_full_fp64_t *, unsigned int, double *, double *) = NULL; +static ComputeStatus (*dl_compute_permanova_fp32)(const char *, unsigned int, const char**, mat_full_fp32_t *, unsigned int, float *, float *) = NULL; + +ComputeStatus compute_permanova_fp64(const char *grouping_filename, unsigned int n_columns, const char* *columns, + mat_full_fp64_t * result, unsigned int permanova_perms, + double *fstats, double *pvalues) { + if (dl_compute_permanova_fp64==NULL) ssu_load("compute_permanova_fp64", (void **) &dl_compute_permanova_fp64); + + (*dl_compute_permanova_fp64)(grouping_filename, n_columns, columns, result, permanova_perms, fstats, pvalues); +} + +ComputeStatus compute_permanova_fp32(const char *grouping_filename, unsigned int n_columns, const char* * columns, + mat_full_fp32_t * result, unsigned int permanova_perms, + float *fstats, float *pvalues) { + if (dl_compute_permanova_fp32==NULL) ssu_load("compute_permanova_fp32", (void **) &dl_compute_permanova_fp32); + + (*dl_compute_permanova_fp32)(grouping_filename, n_columns, columns, result, permanova_perms, fstats, pvalues); +} + + diff --git a/src/api.hpp b/src/api.hpp index 44c40f8..8c6c31f 100644 --- a/src/api.hpp +++ b/src/api.hpp @@ -461,7 +461,7 @@ EXTERN ComputeStatus compute_permanova_fp64(const char *grouping_filename, unsig * okay : no problems encountered * grouping_missing : the filename for the grouping does not exist or is not valid */ -EXTERN ComputeStatus compute_permanova_fp32(const char *grouping_filename, unsigned int n_columns, const char* const* columns, +EXTERN ComputeStatus compute_permanova_fp32(const char *grouping_filename, unsigned int n_columns, const char* * columns, mat_full_fp32_t * result, unsigned int permanova_perms, float *fstats, float *pvalues); From 8669a9cf9ee2a084456e5839d6d17e0054aa8c2d Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 12:55:53 -0700 Subject: [PATCH 11/20] Remove EXTERN from all partial functions. They were never meant to be public and there is no known external use --- src/api.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/api.hpp b/src/api.hpp index 8c6c31f..60728b0 100644 --- a/src/api.hpp +++ b/src/api.hpp @@ -626,7 +626,7 @@ EXTERN IOStatus write_vec(const char* filename, r_vec* result); * unknown_method : the requested method is unknown. */ -EXTERN ComputeStatus partial(const char* biom_filename, const char* tree_filename, +ComputeStatus partial(const char* biom_filename, const char* tree_filename, const char* unifrac_method, bool variance_adjust, double alpha, bool bypass_tips, unsigned int n_substeps, unsigned int stripe_start, unsigned int stripe_stop, partial_mat_t** result); @@ -672,7 +672,7 @@ EXTERN ComputeStatus partial(const char* biom_filename, const char* tree_filenam * ### FOOTER ### * : char, e.g., SSU-PARTIAL-01, same as starting magic */ -EXTERN IOStatus write_partial(const char* filename, const partial_mat_t* result); +IOStatus write_partial(const char* filename, const partial_mat_t* result); /* Read a partial matrix object * @@ -687,7 +687,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 */ -EXTERN IOStatus read_partial(const char* filename, partial_mat_t** result); +IOStatus read_partial(const char* filename, partial_mat_t** result); /* Read a partial matrix object header * @@ -702,7 +702,7 @@ EXTERN IOStatus read_partial(const char* filename, partial_mat_t** result); * bad_header : header seems malformed * unexpected_end : format end not found in expected location */ -EXTERN IOStatus read_partial_header(const char* input_filename, partial_dyn_mat_t** result_out); +IOStatus read_partial_header(const char* input_filename, partial_dyn_mat_t** result_out); /* Read a stripe of a partial matrix * @@ -718,12 +718,12 @@ EXTERN IOStatus read_partial_header(const char* input_filename, partial_dyn_mat_ * bad_header : header seems malformed * unexpected_end : format end not found in expected location */ -EXTERN IOStatus read_partial_one_stripe(partial_dyn_mat_t* result, uint32_t stripe_idx); +IOStatus read_partial_one_stripe(partial_dyn_mat_t* result, uint32_t stripe_idx); /* * Description TBD */ -EXTERN MergeStatus validate_partial(const partial_dyn_mat_t* const * partial_mats, int n_partials); +MergeStatus validate_partial(const partial_dyn_mat_t* const * partial_mats, int n_partials); /* Merge partial results * @@ -738,7 +738,7 @@ EXTERN MergeStatus validate_partial(const partial_dyn_mat_t* const * partial_mat * sample_id_consistency : samples described by stripes are inconsistent * square_mismatch : inconsistency on denotation of square matrix */ -EXTERN MergeStatus merge_partial(partial_mat_t** partial_mats, int n_partials, unsigned int dummy, mat_t** result); +MergeStatus merge_partial(partial_mat_t** partial_mats, int n_partials, unsigned int dummy, mat_t** result); /* Merge partial results * From f8782c42d96139bc8bc3a59691ac7dc72ddb02a8 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 12:58:10 -0700 Subject: [PATCH 12/20] Remove EXTERN from write_mat_hdf5_ functions. They were never meant to be public and there is no known external use --- src/api.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api.hpp b/src/api.hpp index 60728b0..29f00af 100644 --- a/src/api.hpp +++ b/src/api.hpp @@ -488,7 +488,7 @@ EXTERN IOStatus write_mat(const char* filename, mat_t* result); * write_okay : no problems */ // backwards compatible version, deprecated -EXTERN IOStatus write_mat_hdf5_fp64(const char* filename, mat_t* result, unsigned int pcoa_dims, int save_dist); +IOStatus write_mat_hdf5_fp64(const char* filename, mat_t* result, unsigned int pcoa_dims, int save_dist); /* Write a matrix object using hdf5 format, using fp32 precision * @@ -502,7 +502,7 @@ EXTERN IOStatus write_mat_hdf5_fp64(const char* filename, mat_t* result, unsigne * write_okay : no problems */ // backwards compatible version, deprecated -EXTERN IOStatus write_mat_hdf5_fp32(const char* filename, mat_t* result, unsigned int pcoa_dims, int save_dist); +IOStatus write_mat_hdf5_fp32(const char* filename, mat_t* result, unsigned int pcoa_dims, int save_dist); /* Write a matrix object * From 246e7b979f0015bb64230a9d9deefdd19e681447 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 13:36:08 -0700 Subject: [PATCH 13/20] Add write_ functions and fix return values --- combined/libssu.c | 103 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 15 deletions(-) diff --git a/combined/libssu.c b/combined/libssu.c index 19485a9..b3742cd 100644 --- a/combined/libssu.c +++ b/combined/libssu.c @@ -151,7 +151,7 @@ ComputeStatus one_off(const char* biom_filename, const char* tree_filename, bool bypass_tips, unsigned int n_substeps, mat_t** result) { if (dl_one_off==NULL) ssu_load("one_off", (void **) &dl_one_off); - (*dl_one_off)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); + return (*dl_one_off)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); } /*********************************************************************/ @@ -172,7 +172,7 @@ ComputeStatus one_off_matrix_inmem_v2(const support_biom_t *table_data, const su mat_full_fp64_t** result) { if (dl_one_off_matrix_inmem_v2==NULL) ssu_load("one_off_matrix_inmem_v2", (void **) &dl_one_off_matrix_inmem_v2); - (*dl_one_off_matrix_inmem_v2)(table_data, tree_data, unifrac_method, variance_adjust, alpha, + return (*dl_one_off_matrix_inmem_v2)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); } @@ -181,7 +181,7 @@ ComputeStatus one_off_inmem(const support_biom_t *table_data, const support_bptr bool bypass_tips, unsigned int n_substeps, mat_full_fp64_t** result) { if (dl_one_off_inmem==NULL) ssu_load("one_off_inmem", (void **) &dl_one_off_inmem); - (*dl_one_off_inmem)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); + return (*dl_one_off_inmem)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); } ComputeStatus one_off_matrix_inmem_fp32_v2(const support_biom_t *table_data, const support_bptree_t *tree_data, @@ -191,7 +191,7 @@ ComputeStatus one_off_matrix_inmem_fp32_v2(const support_biom_t *table_data, con mat_full_fp32_t** result) { if (dl_one_off_matrix_inmem_fp32_v2==NULL) ssu_load("one_off_matrix_inmem_fp32_v2", (void **) &dl_one_off_matrix_inmem_fp32_v2); - (*dl_one_off_matrix_inmem_fp32_v2)(table_data, tree_data, unifrac_method, variance_adjust, alpha, + return (*dl_one_off_matrix_inmem_fp32_v2)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); } @@ -200,7 +200,7 @@ ComputeStatus one_off_inmem_fp32(const support_biom_t *table_data, const support bool bypass_tips, unsigned int n_substeps, mat_full_fp32_t** result) { if (dl_one_off_inmem_fp32==NULL) ssu_load("one_off_inmem_fp32", (void **) &dl_one_off_inmem_fp32); - (*dl_one_off_inmem_fp32)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); + return (*dl_one_off_inmem_fp32)(table_data, tree_data, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, result); } /*********************************************************************/ @@ -221,7 +221,7 @@ ComputeStatus one_off_matrix_v2(const char* biom_filename, const char* tree_file mat_full_fp64_t** result) { if (dl_one_off_matrix_v2==NULL) ssu_load("one_off_matrix_v2", (void **) &dl_one_off_matrix_v2); - (*dl_one_off_matrix_v2)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + return (*dl_one_off_matrix_v2)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); } @@ -232,7 +232,7 @@ ComputeStatus one_off_matrix(const char* biom_filename, const char* tree_filenam mat_full_fp64_t** result) { if (dl_one_off_matrix==NULL) ssu_load("one_off_matrix", (void **) &dl_one_off_matrix); - (*dl_one_off_matrix)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + return (*dl_one_off_matrix)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, mmap_dir, result); } @@ -243,7 +243,7 @@ ComputeStatus one_off_matrix_fp32_v2(const char* biom_filename, const char* tree mat_full_fp32_t** result) { if (dl_one_off_matrix_fp32_v2==NULL) ssu_load("one_off_matrix_fp32_v2", (void **) &dl_one_off_matrix_fp32_v2); - (*dl_one_off_matrix_fp32_v2)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + return (*dl_one_off_matrix_fp32_v2)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, subsample_depth, subsample_with_replacement, mmap_dir, result); } @@ -254,7 +254,7 @@ ComputeStatus one_off_matrix_fp32(const char* biom_filename, const char* tree_fi mat_full_fp32_t** result) { if (dl_one_off_matrix_fp32==NULL) ssu_load("one_off_matrix_fp32", (void **) &dl_one_off_matrix_fp32); - (*dl_one_off_matrix_fp32)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, + return (*dl_one_off_matrix_fp32)(biom_filename, tree_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, mmap_dir, result); } @@ -265,7 +265,7 @@ ComputeStatus faith_pd_one_off(const char* biom_filename, const char* tree_filen r_vec** result) { if (dl_faith_pd_one_off==NULL) ssu_load("faith_pd_one_off", (void **) &dl_faith_pd_one_off); - (*dl_faith_pd_one_off)(biom_filename, tree_filename, result); + return (*dl_faith_pd_one_off)(biom_filename, tree_filename, result); } /*********************************************************************/ @@ -288,7 +288,7 @@ ComputeStatus unifrac_to_file_v2(const char* biom_filename, const char* tree_fil const char *mmap_dir){ if (dl_unifrac_to_file_v2==NULL) ssu_load("unifrac_to_file_v2", (void **) &dl_unifrac_to_file_v2); - (*dl_unifrac_to_file_v2)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, + return (*dl_unifrac_to_file_v2)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, format, subsample_depth, subsample_with_replacement, pcoa_dims, permanova_perms, grouping_filename, grouping_columns, mmap_dir); } @@ -299,7 +299,7 @@ ComputeStatus unifrac_to_file(const char* biom_filename, const char* tree_filena unsigned int pcoa_dims, const char *mmap_dir) { if (dl_unifrac_to_file==NULL) ssu_load("unifrac_to_file", (void **) &dl_unifrac_to_file); - (*dl_unifrac_to_file)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, + return (*dl_unifrac_to_file)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, format, pcoa_dims, mmap_dir); } @@ -312,7 +312,7 @@ ComputeStatus unifrac_multi_to_file_v2(const char* biom_filename, const char* tr const char *mmap_dir) { if (dl_unifrac_multi_to_file_v2==NULL) ssu_load("unifrac_multi_to_file_v2", (void **) &dl_unifrac_multi_to_file_v2); - (*dl_unifrac_multi_to_file_v2)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, + return (*dl_unifrac_multi_to_file_v2)(biom_filename, tree_filename, out_filename, unifrac_method, variance_adjust, alpha, bypass_tips, n_substeps, format, n_subsamples, subsample_depth, subsample_with_replacement, pcoa_dims, permanova_perms, grouping_filename, grouping_columns, mmap_dir); } @@ -328,7 +328,7 @@ ComputeStatus compute_permanova_fp64(const char *grouping_filename, unsigned int double *fstats, double *pvalues) { if (dl_compute_permanova_fp64==NULL) ssu_load("compute_permanova_fp64", (void **) &dl_compute_permanova_fp64); - (*dl_compute_permanova_fp64)(grouping_filename, n_columns, columns, result, permanova_perms, fstats, pvalues); + return (*dl_compute_permanova_fp64)(grouping_filename, n_columns, columns, result, permanova_perms, fstats, pvalues); } ComputeStatus compute_permanova_fp32(const char *grouping_filename, unsigned int n_columns, const char* * columns, @@ -336,7 +336,80 @@ ComputeStatus compute_permanova_fp32(const char *grouping_filename, unsigned int float *fstats, float *pvalues) { if (dl_compute_permanova_fp32==NULL) ssu_load("compute_permanova_fp32", (void **) &dl_compute_permanova_fp32); - (*dl_compute_permanova_fp32)(grouping_filename, n_columns, columns, result, permanova_perms, fstats, pvalues); + return (*dl_compute_permanova_fp32)(grouping_filename, n_columns, columns, result, permanova_perms, fstats, pvalues); +} + +/*********************************************************************/ + +static IOStatus (*dl_write_mat)(const char*, mat_t*) = NULL; +static IOStatus (*dl_write_mat_from_matrix)(const char*, mat_full_fp64_t*) = NULL; +static IOStatus (*dl_write_vec)(const char*, r_vec*) = NULL; + +IOStatus write_mat(const char* filename, mat_t* result) { + if (dl_write_mat==NULL) ssu_load("write_mat", (void **) &dl_write_mat); + + return (*dl_write_mat)(filename, result); +} + +IOStatus write_mat_from_matrix(const char* filename, mat_full_fp64_t* result) { + if (dl_write_mat_from_matrix==NULL) ssu_load("write_mat_from_matrix", (void **) &dl_write_mat_from_matrix); + + return (*dl_write_mat_from_matrix)(filename, result); +} + +IOStatus write_vec(const char* filename, r_vec* result) { + if (dl_write_vec==NULL) ssu_load("write_vec", (void **) &dl_write_vec); + + return (*dl_write_vec)(filename, result); +} + +/*********************************************************************/ + +static IOStatus (*dl_write_mat_from_matrix_hdf5_fp64_v2)(const char*, mat_full_fp64_t*, unsigned int, int, unsigned int, + const char* *, const char**, const double *, const double *, const unsigned int *, + const char**, const unsigned int *) = NULL; +static IOStatus (*dl_write_mat_from_matrix_hdf5_fp64)(const char*, mat_full_fp64_t*, unsigned int, int) = NULL; +static IOStatus (*dl_write_mat_from_matrix_hdf5_fp32_v2)(const char*, mat_full_fp32_t*, unsigned int, int, unsigned int, + const char**, const char**, const float *, const float *, const unsigned int *, + const char**, const unsigned int *) = NULL; +static IOStatus (*dl_write_mat_from_matrix_hdf5_fp32)(const char*, mat_full_fp32_t*, unsigned int, int) = NULL; + +IOStatus write_mat_from_matrix_hdf5_fp64_v2(const char* output_filename, mat_full_fp64_t* result, + unsigned int pcoa_dims, int save_dist, + unsigned int stat_n_vals, + const char* *stat_method_arr, const char* *stat_name_arr, + const double *stat_val_arr, const double *stat_pval_arr, const unsigned int *stat_perm_count_arr, + const char* *stat_group_name_arr, const unsigned int *stat_group_count_arr) { + if (dl_write_mat_from_matrix_hdf5_fp64_v2==NULL) ssu_load("write_mat_from_matrix_hdf5_fp64_v2", (void **) &dl_write_mat_from_matrix_hdf5_fp64_v2); + + return (*dl_write_mat_from_matrix_hdf5_fp64_v2)(output_filename, result, pcoa_dims, save_dist, stat_n_vals, + stat_method_arr, stat_name_arr, stat_val_arr, stat_pval_arr, stat_perm_count_arr, + stat_group_name_arr, stat_group_count_arr); +} + +IOStatus write_mat_from_matrix_hdf5_fp64(const char* filename, mat_full_fp64_t* result, unsigned int pcoa_dims, int save_dist) { + if (dl_write_mat_from_matrix_hdf5_fp64==NULL) ssu_load("write_mat_from_matrix_hdf5_fp64", (void **) &dl_write_mat_from_matrix_hdf5_fp64); + + return (*dl_write_mat_from_matrix_hdf5_fp64)(filename, result, pcoa_dims, save_dist); +} + +IOStatus write_mat_from_matrix_hdf5_fp32_v2(const char* output_filename, mat_full_fp32_t* result, + unsigned int pcoa_dims, int save_dist, + unsigned int stat_n_vals, + const char* *stat_method_arr, const char* *stat_name_arr, + const float *stat_val_arr, const float *stat_pval_arr, const unsigned int *stat_perm_count_arr, + const char* *stat_group_name_arr, const unsigned int *stat_group_count_arr) { + if (dl_write_mat_from_matrix_hdf5_fp32_v2==NULL) ssu_load("write_mat_from_matrix_hdf5_fp32_v2", (void **) &dl_write_mat_from_matrix_hdf5_fp32_v2); + + return (*dl_write_mat_from_matrix_hdf5_fp32_v2)(output_filename, result, pcoa_dims, save_dist, stat_n_vals, + stat_method_arr, stat_name_arr, stat_val_arr, stat_pval_arr, stat_perm_count_arr, + stat_group_name_arr, stat_group_count_arr); +} + +IOStatus write_mat_from_matrix_hdf5_fp32(const char* filename, mat_full_fp32_t* result, unsigned int pcoa_dims, int save_dist) { + if (dl_write_mat_from_matrix_hdf5_fp32==NULL) ssu_load("write_mat_from_matrix_hdf5_fp32", (void **) &dl_write_mat_from_matrix_hdf5_fp32); + + return (*dl_write_mat_from_matrix_hdf5_fp32)(filename, result, pcoa_dims, save_dist); } From e1f3ba0687e7f452ec9c6bc64f16dad5d3011907 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 14:01:05 -0700 Subject: [PATCH 14/20] Clean up combined makefile --- Makefile | 29 +++++++++++++++++------------ combined/Makefile | 9 ++++++--- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index c31eb2e..b861a31 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,10 @@ -.PHONY: all main api test_binaries test install clean all_combined all_basic all_gpu all_avx2 +.PHONY: test_binaries test install clean all all_combined all_basic all_nv all_nv_avx2 ifeq ($(PLATFORM),Darwin) all: api main install else -all: all_combined - -endif - -clean: - -cd test && make clean - -cd src && make clean - -########### all - -all_combined: all_cpu_basic all_nv all_nv_avx2 +all: all_cpu_basic all_nv all_nv_avx2 all_combined all_cpu_basic: api_cpu_basic main_cpu_basic install_cpu_basic @@ -22,6 +12,15 @@ all_nv: api_nv main_nv install_nv all_nv_avx2: api_nv_avx2 main_nv_avx2 install_nv_avx2 +all_combined: api_combined install_combined + +endif + +clean: + -cd test && make clean + -cd src && make clean + -cd combined && make clean + ########### api api: @@ -36,6 +35,9 @@ api_nv: api_nv_avx2: source ./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 + ########### main main: @@ -64,6 +66,9 @@ install_nv: install_nv_avx2: source ./setup_nv_h5.sh; export BUILD_VARIANT=nv_avx2 ; export BUILD_FULL_OPTIMIZATION=True ; cd src && make install +install_combined: + cd combined && make install + ########### test test_binaries: diff --git a/combined/Makefile b/combined/Makefile index 533b2e4..413ecf1 100644 --- a/combined/Makefile +++ b/combined/Makefile @@ -1,8 +1,11 @@ -.PHONY: all main install clean +.PHONY: all api main install clean -all: main install +all: api install -main: libssu.so +api: libssu.so + +# no-op, just for completeness +main: ifeq ($(PREFIX),) From b9638ba1a8e79763178fed975c7ce5bab76da3c4 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 14:07:13 -0700 Subject: [PATCH 15/20] Update CI to use make all and not explicitly source the nv scripts --- .github/workflows/main.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7f4b2b0..8a07350 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,12 +49,11 @@ jobs: clang -v fi which h5c++ - if [[ "$(uname -s)" == "Linux" && "${{ matrix.fullopt }}" != "False" ]]; + if [[ "$(uname -s)" == "Linux" ]]; then - # always use PGI when fully optimizing - # but never when in compatible/low-optimization mode + # install PGI but do not source it + # the makefile will do it automatically ./scripts/install_hpc_sdk.sh Date: Mon, 8 May 2023 14:16:21 -0700 Subject: [PATCH 16/20] Properly build all_nv last --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b861a31..1c8b04b 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,14 @@ .PHONY: test_binaries test install clean all all_combined all_basic all_nv all_nv_avx2 +# Note: This Makefile will NOT properly work with the -j option + ifeq ($(PLATFORM),Darwin) all: api main install else -all: all_cpu_basic all_nv all_nv_avx2 all_combined + +# 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 all_cpu_basic: api_cpu_basic main_cpu_basic install_cpu_basic From f07781532ce61c4527a6029486e4655a94c383e9 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 14:23:35 -0700 Subject: [PATCH 17/20] Build test_binaries as part of all --- .github/workflows/main.yml | 3 +-- Makefile | 11 ++++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8a07350..625e959 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,9 +61,8 @@ jobs: echo "======= begin env =====" env echo "======= end env =====" - # all == build and install + # all == build (shlib,bins,tests) and install make all - make test_binaries df -h . pushd src if [[ "$(uname -s)" == "Linux" ]]; diff --git a/Makefile b/Makefile index 1c8b04b..809fc24 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ -.PHONY: test_binaries test install clean all all_combined all_basic all_nv all_nv_avx2 +.PHONY: test clean all # Note: This Makefile will NOT properly work with the -j option ifeq ($(PLATFORM),Darwin) -all: api main install +all: api main install 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 +all: all_cpu_basic all_nv_avx2 all_nv all_combined test_binaries_nv all_cpu_basic: api_cpu_basic main_cpu_basic install_cpu_basic @@ -79,6 +79,11 @@ test_binaries: cd src && make test_binaries cd test && make test_binaries +test_binaries_nv: + source ./setup_nv_h5.sh; export BUILD_VARIANT=nv ; export BUILD_FULL_OPTIMIZATION=False ; cd src && make test_binaries + # use the default compiler for the test subdir as it tests the combined shlib + cd test && make test_binaries + test: cd src && make test cd test && make test From adc129e10f45e7957b2f3ee6136ce9ecbc5b1735 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 14:24:48 -0700 Subject: [PATCH 18/20] Revert fullopt testing, as it is now part of the Makefile --- .github/workflows/main.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 625e959..1d46be4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,10 +14,6 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, linux-gpu-cuda] - fullopt: ["True", "False"] - exclude: - - os: linux-gpu-cuda - fullopt: "False" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -57,7 +53,6 @@ jobs: fi df -h . export PERFORMING_CONDA_BUILD=True - export BUILD_FULL_OPTIMIZATION=${{ matrix.fullopt }} echo "======= begin env =====" env echo "======= end env =====" From 97cf7d56fbccfe7bea94bcc6606513e33cab03c0 Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 15:30:02 -0700 Subject: [PATCH 19/20] Add missing definitions --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 809fc24..12280cc 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,9 @@ # Note: This Makefile will NOT properly work with the -j option +PLATFORM := $(shell uname -s) +COMPILER := $(shell ($(CXX) -v 2>&1) | tr A-Z a-z ) + ifeq ($(PLATFORM),Darwin) all: api main install test_binaries From b9aaa92b284c898bfb108eca51898e4992f1cd9c Mon Sep 17 00:00:00 2001 From: Igor Sfiligoi Date: Mon, 8 May 2023 15:47:08 -0700 Subject: [PATCH 20/20] Remove excessive clean --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1d46be4..6788f91 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -62,7 +62,6 @@ jobs: pushd src if [[ "$(uname -s)" == "Linux" ]]; then - make clean rm -f ~/.R/Makevars conda install -q --yes --strict-channel-priority -c conda-forge r-base unset CXXFLAGS