diff --git a/cmake/BuildMisc.cmake b/cmake/BuildMisc.cmake index 2f88432ece3809cc252792234213bffdb25becae..71c146f96151933671a65b19eccfec85343d3cd0 100644 --- a/cmake/BuildMisc.cmake +++ b/cmake/BuildMisc.cmake @@ -6,6 +6,7 @@ macro(libmisc_build) ${PROJECT_SOURCE_DIR}/third_party/sha1.c ${PROJECT_SOURCE_DIR}/third_party/PMurHash.c ${PROJECT_SOURCE_DIR}/third_party/base64.c + ${PROJECT_SOURCE_DIR}/third_party/qsort_arg.c ) if (CC_HAS_WNO_IMPLICIT_FALLTHROUGH) @@ -35,9 +36,6 @@ macro(libmisc_build) if (HAVE_OPENMP) list(APPEND misc_src ${PROJECT_SOURCE_DIR}/third_party/qsort_arg_mt.c) - else() - list(APPEND misc_src - ${PROJECT_SOURCE_DIR}/third_party/qsort_arg.c) endif() add_library(misc STATIC ${misc_src}) diff --git a/third_party/qsort_arg.c b/third_party/qsort_arg.c index 5d0b7ae1c633461dec78a1e919e618a0b9434bd5..4f0cf5adf50481641bef4f8f4f2763b812dbd8f3 100644 --- a/third_party/qsort_arg.c +++ b/third_party/qsort_arg.c @@ -50,6 +50,16 @@ #include <third_party/qsort_arg.h> #include <stdint.h> +enum { + /* + * The size of an array from which it is reasonable to start + * multithread sort. + * If the array size is less than the size below, a single-threaded + * version of qsort will be started.S + */ + MULTITHREAD_SIZE_THRESHOLD = 128 * 1024, +}; + #define min(a, b) (a) < (b) ? a : b static char *med3(char *a, char *b, char *c, @@ -105,8 +115,11 @@ med3(char *a, char *b, char *c, int (*cmp)(const void *a, const void *b, void *a : (cmp(b, c, arg) > 0 ? b : (cmp(a, c, arg) < 0 ? a : c)); } -void -qsort_arg(void *a, size_t n, size_t es, int (*cmp)(const void *a, const void *b, void *arg), void *arg) +/** + * Single-thread version of qsort. + */ +static void +qsort_arg_st(void *a, size_t n, size_t es, int (*cmp)(const void *a, const void *b, void *arg), void *arg) { char *pa, *pb, @@ -199,3 +212,31 @@ loop:SWAPINIT(a, es); } /* qsort_arg(pn - r, r / es, es, cmp, arg);*/ } + +#ifdef HAVE_OPENMP +/** + * Multi-thread version of qsort. Only present when target machine supports + * open MP. + */ +void qsort_arg_mt(void *a, size_t n, size_t es, + int (*cmp)(const void *, const void *, void *), void *arg); +#endif + +/** + * General version of qsort that calls single-threaded of multi-threaded + * qsort depending on open MP availability and given array size. + */ +void +qsort_arg(void *a, size_t n, size_t es, + int (*cmp)(const void *a, const void *b, void *arg), void *arg) +{ +#ifdef HAVE_OPENMP + if (n >= MULTITHREAD_SIZE_THRESHOLD) + qsort_arg_mt(a, n, es, cmp, arg); + else + qsort_arg_st(a, n, es, cmp, arg); +#else + qsort_arg_st(a, n, es, cmp, arg); +#endif +} + diff --git a/third_party/qsort_arg.h b/third_party/qsort_arg.h index 6b9fe44cc012223a8ebeac0dc8c1e8fe8e98ef56..a96e34be68efafff48066519ca31a28cea5cd312 100644 --- a/third_party/qsort_arg.h +++ b/third_party/qsort_arg.h @@ -1,13 +1,19 @@ #ifndef QSORT_ARG_H #define QSORT_ARG_H +#include <trivia/config.h> #include <sys/types.h> #if defined(__cplusplus) extern "C" { #endif /* defined(__cplusplus) */ -void qsort_arg(void *a, size_t n, size_t es, int (*cmp)(const void *a, const void *b, void *arg), void *arg); +/** + * General version of qsort that calls single-threaded of multi-threaded + * qsort depending on open MP availability and given array size. + */ +void qsort_arg(void *a, size_t n, size_t es, + int (*cmp)(const void *a, const void *b, void *arg), void *arg); #if defined(__cplusplus) } diff --git a/third_party/qsort_arg_mt.c b/third_party/qsort_arg_mt.c index 71ccae37022f42ac7366a228b7fd2914d531e14e..21c9ee58a99e7a68081ca1199cac7ab16508f558 100644 --- a/third_party/qsort_arg_mt.c +++ b/third_party/qsort_arg_mt.c @@ -54,6 +54,10 @@ extern "C" { #endif /* defined(__cplusplus) */ +#ifndef HAVE_OPENMP +#error "HAVE_OPENMP macro is not defined" +#endif + #define min(a, b) (a) < (b) ? a : b static char *med3(char *a, char *b, char *c, @@ -218,8 +222,8 @@ qsort_arg_mt_internal(void *a, size_t n, intptr_t es, } void -qsort_arg(void *a, size_t n, size_t es, - int (*cmp)(const void *a, const void *b, void *arg), void *arg) +qsort_arg_mt(void *a, size_t n, size_t es, + int (*cmp)(const void *a, const void *b, void *arg), void *arg) { #pragma omp parallel {