mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Remove TBB parallel_sort patch
Years ago we discovered a problem with TBB's parallel sort, which we patch in our local repo and submitted a change to TBB, which has been accepted. The code to decide whether to use our parallel_sort patch does not work with the latest versions of TBB because it requires including a header that changed names to get the TBB version. We no longer support any TBB version with this bug, so just remove the patch from VTK-m.
This commit is contained in:
parent
0390c8b079
commit
904e784e89
@ -25,7 +25,6 @@ endif()
|
||||
|
||||
vtkm_declare_headers(${headers}
|
||||
ParallelSortTBB.hxx
|
||||
parallel_sort.h
|
||||
)
|
||||
|
||||
#These sources need to always be built
|
||||
|
@ -38,15 +38,6 @@ VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
// correct settings so that we don't clobber any existing function
|
||||
#include <vtkm/internal/Windows.h>
|
||||
|
||||
#include <tbb/tbb_stddef.h>
|
||||
#if (TBB_VERSION_MAJOR == 4) && (TBB_VERSION_MINOR == 2)
|
||||
//we provide an patched implementation of tbb parallel_sort
|
||||
//that fixes ADL for std::swap. This patch has been submitted to Intel
|
||||
//and is fixed in TBB 4.2 update 2.
|
||||
#include <vtkm/cont/tbb/internal/parallel_sort.h>
|
||||
#else
|
||||
#include <tbb/parallel_sort.h>
|
||||
#endif
|
||||
|
||||
#include <numeric>
|
||||
#include <tbb/blocked_range.h>
|
||||
@ -54,6 +45,7 @@ VTKM_THIRDPARTY_PRE_INCLUDE
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/parallel_reduce.h>
|
||||
#include <tbb/parallel_scan.h>
|
||||
#include <tbb/parallel_sort.h>
|
||||
#include <tbb/partitioner.h>
|
||||
#include <tbb/tick_count.h>
|
||||
|
||||
|
@ -1,273 +0,0 @@
|
||||
/*
|
||||
Copyright 2005-2013 Intel Corporation. All Rights Reserved.
|
||||
|
||||
This file is part of Threading Building Blocks.
|
||||
|
||||
Threading Building Blocks is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
Threading Building Blocks is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Threading Building Blocks; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
As a special exception, you may use this file as part of a free software
|
||||
library without restriction. Specifically, if other files instantiate
|
||||
templates or use macros or inline functions from this file, or you compile
|
||||
this file and link it with other files to produce an executable, this
|
||||
file does not by itself cause the resulting executable to be covered by
|
||||
the GNU General Public License. This exception does not however
|
||||
invalidate any other reasons why the executable file might be covered by
|
||||
the GNU General Public License.
|
||||
*/
|
||||
|
||||
#ifndef __TBB_parallel_sort_H
|
||||
#define __TBB_parallel_sort_H
|
||||
|
||||
#include <tbb/blocked_range.h>
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
|
||||
namespace tbb
|
||||
{
|
||||
|
||||
//! @cond INTERNAL
|
||||
namespace internal
|
||||
{
|
||||
|
||||
//! Range used in quicksort to split elements into subranges based on a value.
|
||||
/** The split operation selects a splitter and places all elements less than or equal
|
||||
to the value in the first range and the remaining elements in the second range.
|
||||
@ingroup algorithms */
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
class quick_sort_range : private no_assign
|
||||
{
|
||||
|
||||
inline size_t median_of_three(const RandomAccessIterator& array,
|
||||
size_t l,
|
||||
size_t m,
|
||||
size_t r) const
|
||||
{
|
||||
return comp(array[l], array[m])
|
||||
? (comp(array[m], array[r]) ? m : (comp(array[l], array[r]) ? r : l))
|
||||
: (comp(array[r], array[m]) ? m : (comp(array[r], array[l]) ? r : l));
|
||||
}
|
||||
|
||||
inline size_t pseudo_median_of_nine(const RandomAccessIterator& array,
|
||||
const quick_sort_range& range) const
|
||||
{
|
||||
size_t offset = range.size / 8u;
|
||||
return median_of_three(array,
|
||||
median_of_three(array, 0, offset, offset * 2),
|
||||
median_of_three(array, offset * 3, offset * 4, offset * 5),
|
||||
median_of_three(array, offset * 6, offset * 7, range.size - 1));
|
||||
}
|
||||
|
||||
public:
|
||||
static const size_t grainsize = 500;
|
||||
const Compare& comp;
|
||||
RandomAccessIterator begin;
|
||||
size_t size;
|
||||
|
||||
quick_sort_range(RandomAccessIterator begin_, size_t size_, const Compare& comp_)
|
||||
: comp(comp_)
|
||||
, begin(begin_)
|
||||
, size(size_)
|
||||
{
|
||||
}
|
||||
|
||||
bool empty() const { return size == 0; }
|
||||
bool is_divisible() const { return size >= grainsize; }
|
||||
|
||||
quick_sort_range(quick_sort_range& range, split)
|
||||
: comp(range.comp)
|
||||
{
|
||||
using std::swap;
|
||||
RandomAccessIterator array = range.begin;
|
||||
RandomAccessIterator key0 = range.begin;
|
||||
size_t m = pseudo_median_of_nine(array, range);
|
||||
if (m)
|
||||
swap(array[0], array[m]);
|
||||
|
||||
size_t i = 0;
|
||||
size_t j = range.size;
|
||||
// Partition interval [i+1,j-1] with key *key0.
|
||||
for (;;)
|
||||
{
|
||||
__TBB_ASSERT(i < j, nullptr);
|
||||
// Loop must terminate since array[l]==*key0.
|
||||
do
|
||||
{
|
||||
--j;
|
||||
__TBB_ASSERT(i <= j, "bad ordering relation?");
|
||||
} while (comp(*key0, array[j]));
|
||||
do
|
||||
{
|
||||
__TBB_ASSERT(i <= j, nullptr);
|
||||
if (i == j)
|
||||
goto partition;
|
||||
++i;
|
||||
} while (comp(array[i], *key0));
|
||||
if (i == j)
|
||||
goto partition;
|
||||
swap(array[i], array[j]);
|
||||
}
|
||||
partition:
|
||||
// Put the partition key were it belongs
|
||||
swap(array[j], *key0);
|
||||
// array[l..j) is less or equal to key.
|
||||
// array(j..r) is greater or equal to key.
|
||||
// array[j] is equal to key
|
||||
i = j + 1;
|
||||
begin = array + i;
|
||||
size = range.size - i;
|
||||
range.size = j;
|
||||
}
|
||||
};
|
||||
|
||||
#if __TBB_TASK_GROUP_CONTEXT
|
||||
//! Body class used to test if elements in a range are presorted
|
||||
/** @ingroup algorithms */
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
class quick_sort_pretest_body : internal::no_assign
|
||||
{
|
||||
const Compare& comp;
|
||||
|
||||
public:
|
||||
quick_sort_pretest_body(const Compare& _comp)
|
||||
: comp(_comp)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(const blocked_range<RandomAccessIterator>& range) const
|
||||
{
|
||||
task& my_task = task::self();
|
||||
RandomAccessIterator my_end = range.end();
|
||||
|
||||
int i = 0;
|
||||
for (RandomAccessIterator k = range.begin(); k != my_end; ++k, ++i)
|
||||
{
|
||||
if (i % 64 == 0 && my_task.is_cancelled())
|
||||
break;
|
||||
|
||||
// The k-1 is never out-of-range because the first chunk starts at begin+serial_cutoff+1
|
||||
if (comp(*(k), *(k - 1)))
|
||||
{
|
||||
my_task.cancel_group_execution();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif /* __TBB_TASK_GROUP_CONTEXT */
|
||||
|
||||
//! Body class used to sort elements in a range that is smaller than the grainsize.
|
||||
/** @ingroup algorithms */
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
struct quick_sort_body
|
||||
{
|
||||
void operator()(const quick_sort_range<RandomAccessIterator, Compare>& range) const
|
||||
{
|
||||
//SerialQuickSort( range.begin, range.size, range.comp );
|
||||
std::sort(range.begin, range.begin + range.size, range.comp);
|
||||
}
|
||||
};
|
||||
|
||||
//! Wrapper method to initiate the sort by calling parallel_for.
|
||||
/** @ingroup algorithms */
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void parallel_quick_sort(RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp)
|
||||
{
|
||||
#if __TBB_TASK_GROUP_CONTEXT
|
||||
task_group_context my_context;
|
||||
const int serial_cutoff = 9;
|
||||
|
||||
__TBB_ASSERT(begin + serial_cutoff < end, "min_parallel_size is smaller than serial cutoff?");
|
||||
RandomAccessIterator k;
|
||||
for (k = begin; k != begin + serial_cutoff; ++k)
|
||||
{
|
||||
if (comp(*(k + 1), *k))
|
||||
{
|
||||
goto do_parallel_quick_sort;
|
||||
}
|
||||
}
|
||||
|
||||
parallel_for(blocked_range<RandomAccessIterator>(k + 1, end),
|
||||
quick_sort_pretest_body<RandomAccessIterator, Compare>(comp),
|
||||
auto_partitioner(),
|
||||
my_context);
|
||||
|
||||
if (my_context.is_group_execution_cancelled())
|
||||
do_parallel_quick_sort:
|
||||
#endif /* __TBB_TASK_GROUP_CONTEXT */
|
||||
parallel_for(quick_sort_range<RandomAccessIterator, Compare>(begin, end - begin, comp),
|
||||
quick_sort_body<RandomAccessIterator, Compare>(),
|
||||
auto_partitioner());
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
//! @endcond
|
||||
|
||||
//! @cond INTERNAL
|
||||
/** \page parallel_sort_iter_req Requirements on iterators for parallel_sort
|
||||
Requirements on value type \c T of \c RandomAccessIterator for \c parallel_sort:
|
||||
- \code void swap( T& x, T& y ) \endcode Swaps \c x and \c y
|
||||
- \code bool Compare::operator()( const T& x, const T& y ) \endcode
|
||||
True if x comes before y;
|
||||
**/
|
||||
|
||||
/** \name parallel_sort
|
||||
See also requirements on \ref parallel_sort_iter_req "iterators for parallel_sort". **/
|
||||
//@{
|
||||
|
||||
//! Sorts the data in [begin,end) using the given comparator
|
||||
/** The compare function object is used for all comparisons between elements during sorting.
|
||||
The compare object must define a bool operator() function.
|
||||
@ingroup algorithms **/
|
||||
//! @endcond
|
||||
template <typename RandomAccessIterator, typename Compare>
|
||||
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp)
|
||||
{
|
||||
const int min_parallel_size = 500;
|
||||
if (end > begin)
|
||||
{
|
||||
if (end - begin < min_parallel_size)
|
||||
{
|
||||
std::sort(begin, end, comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
internal::parallel_quick_sort(begin, end, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Sorts the data in [begin,end) with a default comparator \c std::less<RandomAccessIterator>
|
||||
/** @ingroup algorithms **/
|
||||
template <typename RandomAccessIterator>
|
||||
inline void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
|
||||
{
|
||||
parallel_sort(
|
||||
begin, end, std::less<typename std::iterator_traits<RandomAccessIterator>::value_type>());
|
||||
}
|
||||
|
||||
//! Sorts the data in the range \c [begin,end) with a default comparator \c std::less<T>
|
||||
/** @ingroup algorithms **/
|
||||
template <typename T>
|
||||
inline void parallel_sort(T* begin, T* end)
|
||||
{
|
||||
parallel_sort(begin, end, std::less<T>());
|
||||
}
|
||||
//@}
|
||||
|
||||
} // namespace tbb
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user