⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omptl_tools.h

📁 omptl使用openmp多核库优化过的STL库
💻 H
字号:
// Copyright (C) 2006 Fokko Beekhof// Email contact: Fokko.Beekhof@cui.unige.ch// The OMPTL library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.// This library 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// Lesser General Public License for more details.// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA#ifndef OMPTL_TOOLS_H#define OMPTL_TOOLS_H#include <utility>#include <vector>#include <cassert>#include <algorithm>namespace omptl{// Log of the number of operations that is expected to run faster in a single// thread.const unsigned C = 8;template <typename T>T _log2N(T n){	if (n == 0)		return 0;	const unsigned b[] =#if (WORD_BIT == 32)		{0x2u, 0xCu, 0xF0u, 0xFF00u, 0xFFFF0000u};#else		{0x2u, 0xCu, 0xF0u, 0xFF00u, 0xFFFF0000u, 0xFFFFFFFF00000000u};#endif	const T S[] = {1u, 2u, 4u, 8u, 16u, 32u, 64u, 128u};	T result = 0u; // result of log2(v) will go here	for (int i = static_cast<int>(sizeof(T)); i >= 0; --i)	{		if (n & b[i])		{			n >>= S[i];			result |= S[i];		}	}	return result;}template<typename Iterator>bool _linear_serial_is_faster(Iterator first, Iterator last,			     const unsigned P){	OMPTL_ASSERT(P > 0u);	OMPTL_ASSERT(::std::distance(first, last) >= 0);	const unsigned N = ::std::distance(first, last);	const unsigned l = _log2N(N);	return (N < 2u*P) || (l < C);}template<typename Iterator>bool _logn_serial_is_faster(Iterator first, Iterator last,			    const unsigned P){	OMPTL_ASSERT(P > 0u);	OMPTL_ASSERT(::std::distance(first, last) >= 0);	const unsigned N = ::std::distance(first, last);	const unsigned l = _log2N(N);	return (N < 2u*P) || (l < (1 << C));}template<typename Iterator>bool _nlogn_serial_is_faster(Iterator first, Iterator last,			    const unsigned P){	OMPTL_ASSERT(P > 0u);	OMPTL_ASSERT(::std::distance(first, last) >= 0);	const unsigned N = ::std::distance(first, last);	const unsigned l = _log2N(N);	return (N < 2u*P) || (l*N < (1 << C));}template<typename Iterator1, typename Iterator2>void _copy_partitions(		const ::std::pair<Iterator1, Iterator1> *source_partitions,		Iterator2 first, Iterator2 *dest_partitions,		const unsigned P){	for (unsigned i = 0; i < P; ++i)	{		dest_partitions[i] = first;		// The last "advance is very important, it may create space		// if it is an InsertIterator or something like that.		::std::advance(first, ::std::distance(						source_partitions[i].first,						source_partitions[i].second) );	}}// Divide a given range into P partitionstemplate<typename Iterator>void _partition_range(Iterator first, Iterator last,		::std::pair<Iterator, Iterator> *partitions,		const unsigned P){	typedef ::std::pair<Iterator, Iterator> Partition;	const unsigned N = ::std::distance(first, last);	const unsigned range = N / P + ((N%P)? 1 : 0);	OMPTL_ASSERT(2u*P <= N);	OMPTL_ASSERT(range <= N);	// All but last partition have same range	Iterator currentLast = first;	::std::advance(currentLast, range);	for (unsigned i = 0; i < P - 1; ++i)	{		partitions[i] = Partition(first, currentLast);		::std::advance(first, range);		::std::advance(currentLast, range);	}	// Last range may be shorter	partitions[P - 1] = Partition(first, last);}// Given a range, re-arrange the items such that all elements smaller than// the pivot precede all other values. Returns an Iterator to the first// element not smaller than the pivot.template<typename Iterator, class StrictWeakOrdering>Iterator _stable_pivot_range(Iterator first, Iterator last,	const typename ::std::iterator_traits<Iterator>::value_type pivot,	StrictWeakOrdering comp = std::less<		typename ::std::iterator_traits<Iterator>::value_type>()){	Iterator pivotIt = last;	while (first < last)	{		if (comp(*first, pivot))			++first;		else		{			Iterator high = first;			while ( (++high < last) && !comp(*high, pivot) )				/* nop */;			if (high < last)				::std::iter_swap(first, last);			first = pivotIt = ++high;		}	}	return pivotIt;}template<typename Iterator, class StrictWeakOrdering>Iterator _pivot_range(Iterator first, Iterator last,	const typename ::std::iterator_traits<Iterator>::value_type pivot,	StrictWeakOrdering comp){	while (first < last)	{		if (comp(*first, pivot))			++first;		else		{			while ( (first < --last) && !comp(*last, pivot) )				/* nop */;			::std::iter_swap(first, last);		}	}	return last;}template<typename Iterator, class StrictWeakOrdering>void _partition_range_by_pivots(Iterator first, Iterator last,const ::std::vector<typename ::std::iterator_traits<Iterator>::value_type>	&pivots,	::std::pair<Iterator, Iterator> *partitions,	StrictWeakOrdering comp, const unsigned P){	typedef ::std::pair<Iterator, Iterator> Partition;	Iterator ptable[P];	typename ::std::iterator_traits<Iterator>::value_type		pvts[pivots.size()];	::std::vector<Iterator> borders;	bool used[pivots.size()];	::std::fill(used, used + pivots.size(), false);	borders.push_back(first);	borders.push_back(last);	partitions[0].first	= first;	partitions[0].second	= last;	unsigned p = 1;	for (/* nop */; (1 << p) <= (int)P; ++p)	{		const int PROC = (1 << p);		const int PIVOTS = (1 << (p-1));		OMPTL_ASSERT(PIVOTS <= (int)pivots.size());		int t;		#pragma omp parallel for// // default(shared), private(t)		for (t = 0; t < PIVOTS; ++t)		{			const int index = int(P / PROC) +						2 * t * int(P / PROC) - 1;			OMPTL_ASSERT(index < (int)pivots.size());			OMPTL_ASSERT(!used[index]);			used[index] = true;			pvts[t] = pivots[index];/*::std::cout << "pvts T: " << t << " --> " << index <<	" " << pvts[t] << ::std::endl;*/		}		#pragma omp parallel for// // default(shared), private(t)		for (t = 0; t < PIVOTS; ++t)			ptable[t] = _pivot_range(partitions[t].first,						 partitions[t].second,						 pvts[t], comp);		for (t = 0; t < PIVOTS; ++t)		{// ::std::cout << "ADD: " << ::std::distance(first, ptable[t]) << ::std::endl;			borders.push_back(ptable[t]);		}		::std::sort(borders.begin(), borders.end());		#pragma omp parallel for // default(shared), private(t)		for (t = 0; t < (int)borders.size() - 1; ++t)		{			partitions[t].first	= borders[t];			partitions[t].second	= borders[t + 1];		}/*::std::cout << "PASS: " << p << ::std::endl;		for (t = 0; t < (1 << p); ++t)::std::cout << t << ": " << ::std::distance(first, partitions[t].first)		<< " - " << ::std::distance(first, partitions[t].second)		<< ::std::endl;*/	}	for (unsigned i = 0; i < pivots.size(); ++i)		if(!used[i])			pvts[i] = pivots[i];	int t;	#pragma omp parallel for // default(shared), private(t)	for (t = 0; t < (int)pivots.size(); ++t)		if (!used[t])			ptable[t] = _pivot_range(partitions[t].first,						partitions[t].second,						pvts[t], comp);	for (unsigned i = 0; i < pivots.size(); ++i)	{		if (!used[i])		{// ::std::cout << "LAST ADD: " << ::std::distance(first, ptable[i])// 	<< ::std::endl;			borders.push_back(ptable[i]);		}	}	::std::sort(borders.begin(), borders.end());	OMPTL_ASSERT(borders.size() - 1 == P); 	#pragma omp parallel for // default(shared), private(t)	for (t = 0; t < (int)P; ++t)	{		partitions[t].first	= borders[t];		partitions[t].second	= borders[t + 1];	}// ::std::cout << "LAST: " << p << ::std::endl;// 	for (t = 0; t < P; ++t)// ::std::cout << t << ": " << ::std::distance(first, partitions[t].first)// 	<< " - " << ::std::distance(first, partitions[t].second)// 	<< ::std::endl;}template<typename Iterator>void _partition_range_stable_by_pivots(Iterator first, Iterator last,	const ::std::vector<typename::std::iterator_traits<Iterator>::value_type> &pivots,	::std::pair<Iterator, Iterator> *partitions,	std::less<typename ::std::iterator_traits<Iterator>::value_type> comp,	const unsigned P){	typedef ::std::pair<Iterator, Iterator> Partition;	Iterator start = first;	for (unsigned i = 0; i < P - 1; ++i)	{		Iterator low = start;		while (low < last)		{			// Find a value not lower than the pivot.			while( (*low < pivots[i]) && (low < last) )				::std::advance(low, 1);			// Entire range scanned ?			if (low == last) break;			// Find a value lower than the pivot, starting from			// low, working our way up.			Iterator high = low;			::std::advance(high, 1);			while( !(*high < pivots[i]) && (high < last) )				::std::advance(high, 1);			// Entire range scanned ?			if (high == last) break;			// Swap values			OMPTL_ASSERT( !(*low < pivots[i]) && (*high < pivots[i]) );			::std::iter_swap(low, high);		}		partitions[i] = Partition(start, low);		start = low;	}	partitions[P - 1] = Partition(start, last);}/* * The sample ratio is used to sample more data. This way, the pivots can be * chosen more wisely, which is our only guarantee we can generate partitions * of equal size. */template<typename RandomAccessIterator>void _find_pivots(RandomAccessIterator first, RandomAccessIterator last,	::std::vector<typename::std::iterator_traits<RandomAccessIterator>::value_type> &pivots,	const unsigned P,	unsigned SAMPLE_RATIO = 10){	OMPTL_ASSERT(SAMPLE_RATIO > 0);	const unsigned N = ::std::distance(first, last);	OMPTL_ASSERT(N >= 2u*P);	// Adjust the constant. Erm.	while (SAMPLE_RATIO * (P + 1) > N)		SAMPLE_RATIO /= 2;	pivots.clear();	pivots.reserve(P - 1);	typedef typename	    ::std::iterator_traits<RandomAccessIterator>::value_type value_type;	::std::vector<value_type> samples;	const unsigned NSAMPLES = SAMPLE_RATIO * P + SAMPLE_RATIO;	samples.reserve(NSAMPLES);	for (unsigned i = 0; i < NSAMPLES; ++i)	{		const unsigned offset = i * (N-1) / (NSAMPLES - 1);		OMPTL_ASSERT(offset < N);		samples.push_back(*(first + offset));// std::cout << "offset: " << offset << " sample: " << samples[i] << std::endl;	}	OMPTL_ASSERT(samples.size() == NSAMPLES);	// Sort samples to create relative ordering in data	::std::sort(samples.begin(), samples.end());	// Take pivots from sampled data	for (unsigned i = 1; i < P; ++i)	{		pivots.push_back(samples[i * samples.size() / P]);/*std::cout << "pivot: " << i << " idx: " << (i * samples.size() / P)	<< " " << pivots[i-1] << std::endl;*/	}	OMPTL_ASSERT(pivots.size() == P - 1);}}  // namespace omptl#endif /* OMPTL_TOOLS_H */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -