Skip to content
Snippets Groups Projects
Commit c89de311 authored by Konstantin Osipov's avatar Konstantin Osipov
Browse files

Merge remote-tracking branch 'origin/openmp-avl-tree-index-sort' into stable

parents c82efc03 9be45fed
No related branches found
No related tags found
No related merge requests found
......@@ -29,6 +29,11 @@ macro(libmisc_build)
endif()
endif()
if (HAVE_OPENMP)
list(APPEND misc_src
${PROJECT_SOURCE_DIR}/third_party/qsort_arg_mt.c)
endif()
add_library(misc STATIC ${misc_src})
unset(misc_src)
......
......@@ -39,6 +39,22 @@ if((NOT HAVE_STD_C11 AND NOT HAVE_STD_GNU99) OR
"Please consider upgrade to gcc 4.5+ or clang 3.2+.")
endif()
#
# Check for an omp support
#
set(CMAKE_REQUIRED_FLAGS "-fopenmp -Werror")
check_cxx_source_compiles("int main(void) {
#pragma omp parallel
{
}
return 0;
}" HAVE_OPENMP)
set(CMAKE_REQUIRED_FLAGS "")
if (HAVE_OPENMP)
add_compile_flags("C;CXX" "-fopenmp")
endif()
#
# Perform build type specific configuration.
#
......
......@@ -31,8 +31,6 @@
#include <string.h>
#include <stdlib.h>
#include <third_party/qsort_arg.h>
#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */
......@@ -99,7 +97,7 @@ typedef struct avltree_node_pointers {
* void* avltree_NAME_iterator_reverse_next(avltree_NAME_iterator *i)
*/
#define AVL_DEF(name, realloc) \
#define AVL_DEF(name, realloc, qsort_arg) \
typedef struct avl_##name { \
void *members; \
avltree_node_pointers *lrpointers; \
......
......@@ -83,6 +83,10 @@
* Defined if this is a big-endian system.
*/
#cmakedefine HAVE_BYTE_ORDER_BIG_ENDIAN 1
/*
* Defined if this platform supports openmp and it is enabled
*/
#cmakedefine HAVE_OPENMP 1
/*
* Set if compiler has __builtin_XXX methods.
......
......@@ -33,15 +33,25 @@
#include <avl_tree.h>
#ifdef HAVE_OPENMP
/* Using parallel openmp sort */
#include <third_party/qsort_arg_mt.h>
#define QSORT_ARG_FUNC qsort_arg_mt
#else
/* Using usual sort */
#include <third_party/qsort_arg.h>
#define QSORT_ARG_FUNC qsort_arg
#endif
/**
* Instantiate sptree definitions
*/
#ifdef NDEBUG
AVL_DEF(index, realloc);
AVL_DEF(index, realloc, QSORT_ARG_FUNC);
#else
void *
realloc_avl_inject(void *ptr, size_t size);
AVL_DEF(index, realloc_avl_inject);
AVL_DEF(index, realloc_avl_inject, QSORT_ARG_FUNC);
#endif
class AvlTreeIndex: public Index {
......
......@@ -6,13 +6,14 @@
#include "unit.h"
#include "avl_tree.h"
#include "../third_party/sptree.h"
#include "../third_party/qsort_arg.h"
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif //#ifndef MAX
SPTREE_DEF(test, realloc);
AVL_DEF(test, realloc);
AVL_DEF(test, realloc, qsort_arg);
static int
node_comp(const void *p1, const void *p2, void* unused)
......@@ -106,4 +107,4 @@ main(void)
{
simple_check();
compare_with_sptree_check();
}
\ No newline at end of file
}
/*
* Imported from PostgreSQL sources by Teodor Sigaev <teodor@sigaev.ru>, <sigaev@corp.mail.ru>
*/
/*
* qsort_arg.c: qsort with a passthrough "void *" argument
*
* Modifications from vanilla NetBSD source:
* Add do ... while() macro fix
* Remove __inline, _DIAGASSERTs, __P
* Remove ill-considered "swap_cnt" switch to insertion sort,
* in favor of a simple check for presorted input.
*
* CAUTION: if you change this file, see also qsort.c
*
* $PostgreSQL: pgsql/src/port/qsort_arg.c,v 1.4 2007/03/18 05:36:50 neilc Exp $
*/
/* $NetBSD: qsort.c,v 1.13 2003/08/07 16:43:42 agc Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <third_party/qsort_arg_mt.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */
#define min(a, b) (a) < (b) ? a : b
static char *med3(char *a, char *b, char *c,
int (*cmp)(const void *a, const void *b, void *arg), void *arg);
static void swapfunc(char *, char *, size_t, int);
/*
* Qsort routine based on J. L. Bentley and M. D. McIlroy,
* "Engineering a sort function",
* Software--Practice and Experience 23 (1993) 1249-1265.
* We have modified their original by adding a check for already-sorted input,
* which seems to be a win per discussions on pgsql-hackers around 2006-03-21.
*/
#define swapcode(TYPE, parmi, parmj, n) \
do { \
size_t i = (n) / sizeof (TYPE); \
TYPE *pi = (TYPE *)(void *)(parmi); \
TYPE *pj = (TYPE *)(void *)(parmj); \
do { \
TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
} while (0)
#define SWAPINIT(a, es) swaptype = ((char *)(a) - (char *)0) % sizeof(long) || \
(es) % sizeof(long) ? 2 : (es) == sizeof(long)? 0 : 1;
static void
swapfunc(char *a, char *b, size_t n, int swaptype)
{
if (swaptype <= 1)
swapcode(long, a, b, n);
else
swapcode(char, a, b, n);
}
#define swap(a, b) \
if (swaptype == 0) { \
long t = *(long *)(void *)(a); \
*(long *)(void *)(a) = *(long *)(void *)(b); \
*(long *)(void *)(b) = t; \
} else \
swapfunc(a, b, es, swaptype)
#define vecswap(a, b, n) if ((n) > 0) swapfunc((a), (b), (size_t)(n), swaptype)
static char *
med3(char *a, char *b, char *c, int (*cmp)(const void *a, const void *b, void *arg), void *arg)
{
return cmp(a, b, arg) < 0 ?
(cmp(b, c, arg) < 0 ? b : (cmp(a, c, arg) < 0 ? c : a))
: (cmp(b, c, arg) > 0 ? b : (cmp(a, c, arg) < 0 ? a : c));
}
static void
qsort_arg_mt_internal(void *a, size_t n, size_t es,
int (*cmp)(const void *a, const void *b, void *arg), void *arg)
{
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
intptr_t d, r, swaptype, presorted;
loop:SWAPINIT(a, es);
if (n < 7)
{
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
for (pl = pm; pl > (char *) a && cmp(pl - es, pl, arg) > 0;
pl -= es)
swap(pl, pl - es);
return;
}
presorted = 1;
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
{
if (cmp(pm - es, pm, arg) > 0)
{
presorted = 0;
break;
}
}
if (presorted)
return;
pm = (char *) a + (n / 2) * es;
if (n > 7)
{
pl = (char *) a;
pn = (char *) a + (n - 1) * es;
if (n > 40)
{
d = (n / 8) * es;
pl = med3(pl, pl + d, pl + 2 * d, cmp, arg);
pm = med3(pm - d, pm, pm + d, cmp, arg);
pn = med3(pn - 2 * d, pn - d, pn, cmp, arg);
}
pm = med3(pl, pm, pn, cmp, arg);
}
swap((char*)a, pm);
pa = pb = (char *) a + es;
pc = pd = (char *) a + (n - 1) * es;
for (;;)
{
while (pb <= pc && (r = cmp(pb, a, arg)) <= 0)
{
if (r == 0)
{
swap(pa, pb);
pa += es;
}
pb += es;
}
while (pb <= pc && (r = cmp(pc, a, arg)) >= 0)
{
if (r == 0)
{
swap(pc, pd);
pd -= es;
}
pc -= es;
}
if (pb > pc)
break;
swap(pb, pc);
pb += es;
pc -= es;
}
pn = (char *) a + n * es;
r = min(pa - (char *) a, pb - pa);
vecswap((char*)a, pb - r, r);
r = min(pd - pc, pn - pd - es);
vecswap(pb, pn - r, r);
if ((r = pb - pa) > es) {
#pragma omp task
qsort_arg_mt_internal(a, r / es, es, cmp, arg);
}
if ((r = pd - pc) > es)
{
/* Iterate rather than recurse to save stack space */
a = pn - r;
n = r / es;
goto loop;
}
}
void
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
{
#pragma omp single
qsort_arg_mt_internal(a, n, es, cmp, arg);
}
}
#if defined(__cplusplus)
}
#endif /* defined(__cplusplus) */
#ifndef QSORT_ARG_MT_H
#define QSORT_ARG_MT_H
#include <sys/types.h>
#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */
void qsort_arg_mt(void *a, size_t n, size_t es, int (*cmp)(const void *a, const void *b, void *arg), void *arg);
#if defined(__cplusplus)
}
#endif /* defined(__cplusplus) */
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment