Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

View File

@@ -0,0 +1,52 @@
# Copyright (c) 2005-2020 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Common Makefile that builds and runs example.
PROG=convex_hull_bench
ARGS=
PERF_RUN_ARGS = silent auto 40000000
LIGHT_ARGS = 4 400
# Trying to find if icl.exe is set
CXX1 = $(TBB_CXX)-
CXX2 = $(CXX1:icl.exe-=icl.exe)
CXX = $(CXX2:-=cl.exe)
# The C++ compiler options
# Below, _SECURE_SCL=0 is for VC9 and earlier, and _ITERATOR_DEBUG_LEVEL=0 is for VC10 and later
MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _ITERATOR_DEBUG_LEVEL=0 /D _SECURE_SCL=0 $(CXXFLAGS)
MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS)
all: release test
release: compiler_check
$(CXX) convex_hull_sample.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_sample.exe
$(CXX) convex_hull_bench.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_bench.exe
debug: compiler_check
$(CXX) convex_hull_sample.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_sample.exe
$(CXX) convex_hull_bench.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_bench.exe
clean:
@cmd.exe /C del convex_hull*.exe *.obj *.?db *.manifest
test:
$(PROG) $(ARGS)
perf_build: release
perf_run:
convex_hull_sample $(PERF_RUN_ARGS)
light_test:
$(PROG) $(LIGHT_ARGS)
compiler_check:
@echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly"
@cmd.exe /C del compiler_test

View File

@@ -0,0 +1,184 @@
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __CONVEX_HULL_H__
#define __CONVEX_HULL_H__
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <functional>
#include <climits>
#include "tbb/tick_count.h"
#include "tbb/global_control.h"
#include "../../common/utility/utility.h"
#include "../../common/utility/get_default_num_threads.h"
#include "../../common/utility/fast_random.h"
using namespace std;
namespace cfg {
// convex hull problem user set parameters
long numberOfPoints = 5000000; // problem size
// convex hull grain sizes for 3 subproblems. Be sure 16*GS < 512Kb
const size_t generateGrainSize = 25000;
const size_t findExtremumGrainSize = 25000;
const size_t divideGrainSize = 25000;
};
namespace util {
bool silent = false;
bool verbose = false;
vector<string> OUTPUT;
// utility functionality
void ParseInputArgs(int argc, char* argv[], utility::thread_number_range& threads) {
utility::parse_cli_arguments(
argc,argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.positional_arg(threads,"n-of-threads",utility::thread_number_range_desc)
.positional_arg(cfg::numberOfPoints,"n-of-points","number of points")
.arg(silent,"silent","no output except elapsed time")
.arg(verbose,"verbose","turns verbose ON")
);
//disabling verbose if silent is specified
if (silent) verbose = false;;
}
template <typename T>
struct point {
T x;
T y;
//According to subparagraph 4 of paragraph 12.6.2 "Initializing bases and members" [class.base.init]
//of ANSI-ISO-IEC C++ 2003 standard, POD members will _not_ be initialized if they are not mentioned
//in the base-member initializer list.
//For more details why this needed please see comment in FillRNDPointsVector_buf
point() {}
point(T _x, T _y) : x(_x), y(_y) {}
};
std::ostream& operator<< (std::ostream& o, point<double> const& p) {
return o << "(" << p.x << "," << p.y << ")";
}
struct rng {
static const size_t max_rand = USHRT_MAX;
utility::FastRandom my_fast_random;
rng (size_t seed):my_fast_random(seed) {}
unsigned short operator()(){return my_fast_random.get();}
unsigned short operator()(size_t& seed){return my_fast_random.get(seed);}
};
template < typename T ,typename rng_functor_type>
point<T> GenerateRNDPoint(size_t& count, rng_functor_type random, size_t rand_max) {
/* generates random points on 2D plane so that the cluster
is somewhat circle shaped */
const size_t maxsize=500;
T x = random()*2.0/(double)rand_max - 1;
T y = random()*2.0/(double)rand_max - 1;
T r = (x*x + y*y);
if(r>1) {
count++;
if(count>10) {
if (random()/(double)rand_max > 0.5)
x /= r;
if (random()/(double)rand_max > 0.5)
y /= r;
count = 0;
}
else {
x /= r;
y /= r;
}
}
x = (x+1)*0.5*maxsize;
y = (y+1)*0.5*maxsize;
return point<T>(x,y);
}
template <typename Index>
struct edge {
Index start;
Index end;
edge(Index _p1, Index _p2) : start(_p1), end(_p2) {};
};
template <typename T>
ostream& operator <<(ostream& _ostr, point<T> _p) {
return _ostr << '(' << _p.x << ',' << _p.y << ')';
}
template <typename T>
istream& operator >>(istream& _istr, point<T> _p) {
return _istr >> _p.x >> _p.y;
}
template <typename T>
bool operator ==(point<T> p1, point<T> p2) {
return (p1.x == p2.x && p1.y == p2.y);
}
template <typename T>
bool operator !=(point<T> p1, point<T> p2) {
return !(p1 == p2);
}
template <typename T>
double cross_product(const point<T>& start, const point<T>& end1, const point<T>& end2) {
return ((end1.x-start.x)*(end2.y-start.y)-(end2.x-start.x)*(end1.y-start.y));
}
// Timing functions are based on TBB to always obtain wall-clock time
typedef tbb::tick_count my_time_t;
my_time_t gettime() {
return tbb::tick_count::now();
}
double time_diff(my_time_t start, my_time_t end) {
return (end-start).seconds();
}
void WriteResults(int nthreads, double initTime, double calcTime) {
if(verbose) {
cout << " Step by step hull construction:" << endl;
for(size_t i = 0; i < OUTPUT.size(); ++i)
cout << OUTPUT[i] << endl;
}
if (!silent){
cout
<< " Number of nodes:" << cfg::numberOfPoints
<< " Number of threads:" << nthreads
<< " Initialization time:" << setw(10) << setprecision(3) << initTime
<< " Calculation time:" << setw(10) << setprecision(3) << calcTime
<< endl;
}
}
};
#endif // __CONVEX_HULL_H__

View File

@@ -0,0 +1,631 @@
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This file contains a few implementations, so it may look overly complicated.
The most efficient implementation is also separated into convex_hull_sample.cpp
*/
#include "convex_hull.h"
typedef util::point<double> point_t;
#ifndef USETBB
#define USETBB 1
#endif
#ifndef USECONCVEC
#define USECONCVEC 1
#endif
#if !USETBB // Serial implementation of Quick Hull algorithm
typedef std::vector< point_t > pointVec_t;
void serial_initialize(pointVec_t &points);
// C++ style serial code
class FindXExtremum : public std::unary_function<const point_t&, void> {
public:
typedef enum {
minX, maxX
} extremumType;
FindXExtremum(const point_t& frstPoint, extremumType exType_)
: extrXPoint(frstPoint), exType(exType_) {}
void operator()(const point_t& p) {
if(closerToExtremum(p))
extrXPoint = p;
}
operator point_t () {
return extrXPoint;
}
private:
const extremumType exType;
point_t extrXPoint;
bool closerToExtremum(const point_t &p) const {
switch(exType) {
case minX:
return p.x<extrXPoint.x; break;
case maxX:
return p.x>extrXPoint.x; break;
}
return false; // avoid warning
}
};
template <FindXExtremum::extremumType type>
point_t extremum(const pointVec_t &points) {
assert(!points.empty());
return std::for_each(points.begin(), points.end(), FindXExtremum(points[0], type));
}
class SplitByCP : public std::unary_function<const point_t&, void> {
pointVec_t &reducedSet;
point_t p1, p2;
point_t farPoint;
double howFar;
public:
SplitByCP( point_t _p1, point_t _p2, pointVec_t &_reducedSet)
: p1(_p1), p2(_p2), reducedSet(_reducedSet), howFar(0), farPoint(p1) {}
void operator()(const point_t& p) {
double cp;
if( (p != p1) && (p != p2) ) {
cp = util::cross_product(p1, p2, p);
if(cp>0) {
reducedSet.push_back(p);
if(cp>howFar) {
farPoint = p;
howFar = cp;
}
}
}
}
operator point_t (){
return farPoint;
}
};
point_t divide(const pointVec_t &P, pointVec_t &P_reduced, const point_t &p1, const point_t &p2) {
SplitByCP splitByCP(p1, p2, P_reduced);
point_t farPoint = std::for_each(P.begin(), P.end(), splitByCP);
if(util::verbose) {
std::stringstream ss;
ss << P.size() << " nodes in bucket"<< ", "
<< "dividing by: [ " << p1 << ", " << p2 << " ], "
<< "farthest node: " << farPoint;
util::OUTPUT.push_back(ss.str());
}
return farPoint;
}
void divide_and_conquer(const pointVec_t &P, pointVec_t &H, point_t p1, point_t p2) {
assert(P.size() >= 2);
pointVec_t P_reduced;
pointVec_t H1, H2;
point_t p_far = divide(P, P_reduced, p1, p2);
if (P_reduced.size()<2) {
H.push_back(p1);
H.insert(H.end(), P_reduced.begin(), P_reduced.end());
}
else {
divide_and_conquer(P_reduced, H1, p1, p_far);
divide_and_conquer(P_reduced, H2, p_far, p2);
H.insert(H.end(), H1.begin(), H1.end());
H.insert(H.end(), H2.begin(), H2.end());
}
}
void quickhull(const pointVec_t &points, pointVec_t &hull) {
if (points.size() < 2) {
hull.insert(hull.end(), points.begin(), points.end());
return;
}
point_t p_maxx = extremum<FindXExtremum::maxX>(points);
point_t p_minx = extremum<FindXExtremum::minX>(points);
pointVec_t H;
divide_and_conquer(points, hull, p_maxx, p_minx);
divide_and_conquer(points, H, p_minx, p_maxx);
hull.insert(hull.end(), H.begin(), H.end());
}
int main(int argc, char* argv[]) {
util::ParseInputArgs(argc, argv);
pointVec_t points;
pointVec_t hull;
util::my_time_t tm_init, tm_start, tm_end;
std::cout << "Starting serial version of QUICK HULL algorithm" << std::endl;
tm_init = util::gettime();
serial_initialize(points);
tm_start = util::gettime();
std::cout << "Init time: " << util::time_diff(tm_init, tm_start) << " Points in input: " << points.size() << "\n";
tm_start = util::gettime();
quickhull(points, hull);
tm_end = util::gettime();
std::cout << "Serial time: " << util::time_diff(tm_start, tm_end) << " Points in hull: " << hull.size() << "\n";
}
#else // USETBB - parallel version of Quick Hull algorithm
#include "tbb/parallel_for.h"
#include "tbb/parallel_reduce.h"
#include "tbb/blocked_range.h"
typedef tbb::blocked_range<size_t> range_t;
#if USECONCVEC
#include "tbb/concurrent_vector.h"
typedef tbb::concurrent_vector<point_t> pointVec_t;
void appendVector(const point_t* src, size_t srcSize, pointVec_t& dest) {
std::copy(src, src + srcSize, dest.grow_by(srcSize));
}
void appendVector(const pointVec_t& src, pointVec_t& dest) {
std::copy(src.begin(), src.end(), dest.grow_by(src.size()));
}
void grow_vector_to_at_least(pointVec_t& vect, size_t size) {
vect.grow_to_at_least(size);
}
#else // USE STD::VECTOR - include spin_mutex.h and lock vector operations
#include "tbb/spin_mutex.h"
typedef tbb::spin_mutex mutex_t;
typedef std::vector<point_t> pointVec_t;
void appendVector(mutex_t& insertMutex, const pointVec_t& src, pointVec_t& dest) {
mutex_t::scoped_lock lock(insertMutex);
dest.insert(dest.end(), src.begin(), src.end());
}
void appendVector(mutex_t& insertMutex, const point_t* src, size_t srcSize,
pointVec_t& dest) {
mutex_t::scoped_lock lock(insertMutex);
dest.insert(dest.end(), src, src + srcSize);
}
void grow_vector_to_at_least(mutex_t& mutex, pointVec_t& vect, size_t size) {
mutex_t::scoped_lock lock(mutex);
if (vect.size()< size){
vect.resize(size);
}
}
#endif // USECONCVEC
class FillRNDPointsVector {
pointVec_t &points;
public:
static const size_t grainSize = cfg::generateGrainSize;
#if !USECONCVEC
static mutex_t pushBackMutex;
#endif // USECONCVEC
explicit FillRNDPointsVector(pointVec_t& _points)
: points(_points){}
void operator()(const range_t& range) const {
util::rng the_rng(range.begin());
const size_t i_end = range.end();
size_t count = 0;
#if USECONCVEC
points.grow_to_at_least(i_end);
#else // Locked enlarge to a not thread-safe STD::VECTOR
grow_vector_to_at_least(pushBackMutex,points,i_end);
#endif // USECONCVEC
for(size_t i = range.begin(); i != i_end; ++i) {
points[i]=util::GenerateRNDPoint<double>(count,the_rng,util::rng::max_rand);
}
}
};
class FillRNDPointsVector_buf {
pointVec_t &points;
public:
static const size_t grainSize = cfg::generateGrainSize;
#if !USECONCVEC
static mutex_t insertMutex;
#endif // USECONCVEC
explicit FillRNDPointsVector_buf(pointVec_t& _points)
: points(_points){}
void operator()(const range_t& range) const {
util::rng the_rng(range.begin());
const size_t i_end = range.end();
size_t count = 0, j = 0;
point_t tmp_vec[grainSize];
for(size_t i=range.begin(); i!=i_end; ++i) {
tmp_vec[j++] = util::GenerateRNDPoint<double>(count,the_rng,util::rng::max_rand);
}
#if USECONCVEC
grow_vector_to_at_least(points,range.end());
#else // USE STD::VECTOR
grow_vector_to_at_least(insertMutex,points,range.end());
#endif // USECONCVEC
std::copy(tmp_vec, tmp_vec+j,points.begin()+range.begin());
}
};
#if !USECONCVEC
mutex_t FillRNDPointsVector::pushBackMutex = mutex_t();
mutex_t FillRNDPointsVector_buf::insertMutex = mutex_t();
#endif
template<typename BodyType>
void initialize(pointVec_t &points) {
//This function generate the same series of point on every call.
//Reproducibility is needed for benchmarking to produce reliable results.
//It is achieved through the following points:
// - FillRNDPointsVector_buf instance has its own local instance
// of random number generator, which in turn does not use any global data
// - tbb::simple_partitioner produce the same set of ranges on every call to
// tbb::parallel_for
// - local RNG instances are seeded by the starting indexes of corresponding ranges
// - grow_to_at_least() enables putting points into the resulting vector in deterministic order
// (unlike concurrent push_back or grow_by).
// In the buffered version, a temporary storage for as much as grainSize elements
// is allocated inside the body. Since auto_partitioner may increase effective
// range size which would cause a crash, simple partitioner has to be used.
tbb::parallel_for(range_t(0, cfg::numberOfPoints, BodyType::grainSize),
BodyType(points), tbb::simple_partitioner());
}
class FindXExtremum {
public:
typedef enum {
minX, maxX
} extremumType;
static const size_t grainSize = cfg::findExtremumGrainSize;
FindXExtremum(const pointVec_t& points_, extremumType exType_)
: points(points_), exType(exType_), extrXPoint(points[0]) {}
FindXExtremum(const FindXExtremum& fxex, tbb::split)
: points(fxex.points), exType(fxex.exType), extrXPoint(fxex.extrXPoint) {}
void operator()(const range_t& range) {
const size_t i_end = range.end();
if(!range.empty()) {
for(size_t i = range.begin(); i != i_end; ++i) {
if(closerToExtremum(points[i])) {
extrXPoint = points[i];
}
}
}
}
void join(const FindXExtremum &rhs) {
if(closerToExtremum(rhs.extrXPoint)) {
extrXPoint = rhs.extrXPoint;
}
}
point_t extremeXPoint() {
return extrXPoint;
}
private:
const pointVec_t &points;
const extremumType exType;
point_t extrXPoint;
bool closerToExtremum(const point_t &p) const {
switch(exType) {
case minX:
return p.x<extrXPoint.x; break;
case maxX:
return p.x>extrXPoint.x; break;
}
return false; // avoid warning
}
};
template <FindXExtremum::extremumType type>
point_t extremum(const pointVec_t &P) {
FindXExtremum fxBody(P, type);
tbb::parallel_reduce(range_t(0, P.size(), FindXExtremum::grainSize), fxBody);
return fxBody.extremeXPoint();
}
class SplitByCP {
const pointVec_t &initialSet;
pointVec_t &reducedSet;
point_t p1, p2;
point_t farPoint;
double howFar;
public:
static const size_t grainSize = cfg::divideGrainSize;
#if !USECONCVEC
static mutex_t pushBackMutex;
#endif // USECONCVEC
SplitByCP( point_t _p1, point_t _p2,
const pointVec_t &_initialSet, pointVec_t &_reducedSet)
: p1(_p1), p2(_p2),
initialSet(_initialSet), reducedSet(_reducedSet),
howFar(0), farPoint(p1) {
}
SplitByCP( SplitByCP& sbcp, tbb::split )
: p1(sbcp.p1), p2(sbcp.p2),
initialSet(sbcp.initialSet), reducedSet(sbcp.reducedSet),
howFar(0), farPoint(p1) {}
void operator()( const range_t& range ) {
const size_t i_end = range.end();
double cp;
for(size_t i=range.begin(); i!=i_end; ++i) {
if( (initialSet[i] != p1) && (initialSet[i] != p2) ) {
cp = util::cross_product(p1, p2, initialSet[i]);
if(cp>0) {
#if USECONCVEC
reducedSet.push_back(initialSet[i]);
#else // Locked push_back to a not thread-safe STD::VECTOR
{
mutex_t::scoped_lock lock(pushBackMutex);
reducedSet.push_back(initialSet[i]);
}
#endif // USECONCVEC
if(cp>howFar) {
farPoint = initialSet[i];
howFar = cp;
}
}
}
}
}
void join(const SplitByCP& rhs) {
if(rhs.howFar>howFar) {
howFar = rhs.howFar;
farPoint = rhs.farPoint;
}
}
point_t farthestPoint() const {
return farPoint;
}
};
class SplitByCP_buf {
const pointVec_t &initialSet;
pointVec_t &reducedSet;
point_t p1, p2;
point_t farPoint;
double howFar;
public:
static const size_t grainSize = cfg::divideGrainSize;
#if !USECONCVEC
static mutex_t insertMutex;
#endif // USECONCVEC
SplitByCP_buf( point_t _p1, point_t _p2,
const pointVec_t &_initialSet, pointVec_t &_reducedSet)
: p1(_p1), p2(_p2),
initialSet(_initialSet), reducedSet(_reducedSet),
howFar(0), farPoint(p1) {}
SplitByCP_buf(SplitByCP_buf& sbcp, tbb::split)
: p1(sbcp.p1), p2(sbcp.p2),
initialSet(sbcp.initialSet), reducedSet(sbcp.reducedSet),
howFar(0), farPoint(p1) {}
void operator()(const range_t& range) {
const size_t i_end = range.end();
size_t j = 0;
double cp;
point_t tmp_vec[grainSize];
for(size_t i = range.begin(); i != i_end; ++i) {
if( (initialSet[i] != p1) && (initialSet[i] != p2) ) {
cp = util::cross_product(p1, p2, initialSet[i]);
if(cp>0) {
tmp_vec[j++] = initialSet[i];
if(cp>howFar) {
farPoint = initialSet[i];
howFar = cp;
}
}
}
}
#if USECONCVEC
appendVector(tmp_vec, j, reducedSet);
#else // USE STD::VECTOR
appendVector(insertMutex, tmp_vec, j, reducedSet);
#endif // USECONCVEC
}
void join(const SplitByCP_buf& rhs) {
if(rhs.howFar>howFar) {
howFar = rhs.howFar;
farPoint = rhs.farPoint;
}
}
point_t farthestPoint() const {
return farPoint;
}
};
#if !USECONCVEC
mutex_t SplitByCP::pushBackMutex = mutex_t();
mutex_t SplitByCP_buf::insertMutex = mutex_t();
#endif
template <typename BodyType>
point_t divide(const pointVec_t &P, pointVec_t &P_reduced,
const point_t &p1, const point_t &p2) {
BodyType body(p1, p2, P, P_reduced);
// Must use simple_partitioner (see the comment in initialize() above)
tbb::parallel_reduce(range_t(0, P.size(), BodyType::grainSize),
body, tbb::simple_partitioner() );
if(util::verbose) {
std::stringstream ss;
ss << P.size() << " nodes in bucket"<< ", "
<< "dividing by: [ " << p1 << ", " << p2 << " ], "
<< "farthest node: " << body.farthestPoint();
util::OUTPUT.push_back(ss.str());
}
return body.farthestPoint();
}
void divide_and_conquer(const pointVec_t &P, pointVec_t &H,
point_t p1, point_t p2, bool buffered) {
assert(P.size() >= 2);
pointVec_t P_reduced;
pointVec_t H1, H2;
point_t p_far;
if(buffered) {
p_far = divide<SplitByCP_buf>(P, P_reduced, p1, p2);
} else {
p_far = divide<SplitByCP>(P, P_reduced, p1, p2);
}
if (P_reduced.size()<2) {
H.push_back(p1);
#if USECONCVEC
appendVector(P_reduced, H);
#else // insert into STD::VECTOR
H.insert(H.end(), P_reduced.begin(), P_reduced.end());
#endif
}
else {
divide_and_conquer(P_reduced, H1, p1, p_far, buffered);
divide_and_conquer(P_reduced, H2, p_far, p2, buffered);
#if USECONCVEC
appendVector(H1, H);
appendVector(H2, H);
#else // insert into STD::VECTOR
H.insert(H.end(), H1.begin(), H1.end());
H.insert(H.end(), H2.begin(), H2.end());
#endif
}
}
void quickhull(const pointVec_t &points, pointVec_t &hull, bool buffered) {
if (points.size() < 2) {
#if USECONCVEC
appendVector(points, hull);
#else // STD::VECTOR
hull.insert(hull.end(), points.begin(), points.end());
#endif // USECONCVEC
return;
}
point_t p_maxx = extremum<FindXExtremum::maxX>(points);
point_t p_minx = extremum<FindXExtremum::minX>(points);
pointVec_t H;
divide_and_conquer(points, hull, p_maxx, p_minx, buffered);
divide_and_conquer(points, H, p_minx, p_maxx, buffered);
#if USECONCVEC
appendVector(H, hull);
#else // STD::VECTOR
hull.insert(hull.end(), H.begin(), H.end());
#endif // USECONCVEC
}
int main(int argc, char* argv[]) {
utility::thread_number_range threads(utility::get_default_num_threads);
util::ParseInputArgs(argc, argv, threads);
int nthreads;
util::my_time_t tm_init, tm_start, tm_end;
#if USECONCVEC
std::cout << "Starting TBB unbuffered push_back version of QUICK HULL algorithm" << std::endl;
#else
std::cout << "Starting STL locked unbuffered push_back version of QUICK HULL algorithm" << std::endl;
#endif // USECONCVEC
for(nthreads=threads.first; nthreads<=threads.last; nthreads=threads.step(nthreads)) {
pointVec_t points;
pointVec_t hull;
tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
tm_init = util::gettime();
initialize<FillRNDPointsVector>(points);
tm_start = util::gettime();
std::cout << "Parallel init time on " << nthreads << " threads: " << util::time_diff(tm_init, tm_start) << " Points in input: " << points.size() << "\n";
tm_start = util::gettime();
quickhull(points, hull, false);
tm_end = util::gettime();
std::cout << "Time on " << nthreads << " threads: " << util::time_diff(tm_start, tm_end) << " Points in hull: " << hull.size() << "\n";
}
#if USECONCVEC
std::cout << "Starting TBB buffered version of QUICK HULL algorithm" << std::endl;
#else
std::cout << "Starting STL locked buffered version of QUICK HULL algorithm" << std::endl;
#endif
for(nthreads=threads.first; nthreads<=threads.last; nthreads=threads.step(nthreads)) {
pointVec_t points;
pointVec_t hull;
tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
tm_init = util::gettime();
initialize<FillRNDPointsVector_buf>(points);
tm_start = util::gettime();
std::cout << "Init time on " << nthreads << " threads: " << util::time_diff(tm_init, tm_start) << " Points in input: " << points.size() << "\n";
tm_start = util::gettime();
quickhull(points, hull, true);
tm_end = util::gettime();
std::cout << "Time on " << nthreads << " threads: " << util::time_diff(tm_start, tm_end) << " Points in hull: " << hull.size() << "\n";
}
return 0;
}
#endif // USETBB
void serial_initialize(pointVec_t &points) {
points.reserve(cfg::numberOfPoints);
unsigned int rseed=1;
for(size_t i=0, count=0; long(i)<cfg::numberOfPoints; ++i) {
points.push_back(util::GenerateRNDPoint<double>(count,&std::rand,RAND_MAX ));
}
}

View File

@@ -0,0 +1,293 @@
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This file contains the TBB-based implementation of convex hull algortihm.
It corresponds to the following settings in convex_hull_bench.cpp:
- USETBB defined to 1
- USECONCVEC defined to 1
- INIT_ONCE defined to 0
- only buffered version is used
*/
#include "convex_hull.h"
#include "tbb/parallel_for.h"
#include "tbb/parallel_reduce.h"
#include "tbb/blocked_range.h"
#include "tbb/tick_count.h"
#include "tbb/concurrent_vector.h"
typedef util::point<double> point_t;
typedef tbb::concurrent_vector< point_t > pointVec_t;
typedef tbb::blocked_range<size_t> range_t;
void appendVector(const point_t* src, size_t srcSize, pointVec_t& dest) {
std::copy(src, src + srcSize, dest.grow_by(srcSize));
}
void appendVector(const pointVec_t& src, pointVec_t& dest) {
std::copy(src.begin(), src.end(), dest.grow_by(src.size()));
}
class FillRNDPointsVector_buf {
pointVec_t &points;
public:
static const size_t grainSize = cfg::generateGrainSize;
explicit FillRNDPointsVector_buf(pointVec_t& _points)
: points(_points) {}
void operator()(const range_t& range) const {
util::rng the_rng(range.begin());
const size_t i_end = range.end();
size_t count = 0, j = 0;
point_t tmp_vec[grainSize];
for(size_t i=range.begin(); i!=i_end; ++i) {
tmp_vec[j++] = util::GenerateRNDPoint<double>(count, the_rng, util::rng::max_rand);
}
//Here we have race condition. Elements being written to may be still under construction.
//For C++ 2003 it is workarounded by vector element type which default constructor does not touch memory,
//it being constructed on. See comments near default ctor of point class for more details.
//Strictly speaking it is UB.
//TODO: need to find more reliable/correct way
points.grow_to_at_least(range.end());
std::copy(tmp_vec, tmp_vec+j,points.begin()+range.begin());
}
};
void initialize(pointVec_t &points) {
//This function generate the same series of point on every call.
//Reproducibility is needed for benchmarking to produce reliable results.
//It is achieved through the following points:
// - FillRNDPointsVector_buf instance has its own local instance
// of random number generator, which in turn does not use any global data
// - tbb::simple_partitioner produce the same set of ranges on every call to
// tbb::parallel_for
// - local RNG instances are seeded by the starting indexes of corresponding ranges
// - grow_to_at_least() enables putting points into the resulting vector in deterministic order
// (unlike concurrent push_back or grow_by).
// In the buffered version, a temporary storage for as much as grainSize elements
// is allocated inside the body. Since auto_partitioner may increase effective
// range size which would cause a crash, simple partitioner has to be used.
tbb::parallel_for(range_t(0, cfg::numberOfPoints, FillRNDPointsVector_buf::grainSize),
FillRNDPointsVector_buf(points), tbb::simple_partitioner());
}
class FindXExtremum {
public:
typedef enum {
minX, maxX
} extremumType;
static const size_t grainSize = cfg::findExtremumGrainSize;
FindXExtremum(const pointVec_t& points_, extremumType exType_)
: points(points_), exType(exType_), extrXPoint(points[0]) {}
FindXExtremum(const FindXExtremum& fxex, tbb::split)
// Can run in parallel with fxex.operator()() or fxex.join().
// The data race reported by tools is harmless.
: points(fxex.points), exType(fxex.exType), extrXPoint(fxex.extrXPoint) {}
void operator()(const range_t& range) {
const size_t i_end = range.end();
if(!range.empty()) {
for(size_t i = range.begin(); i != i_end; ++i) {
if(closerToExtremum(points[i])) {
extrXPoint = points[i];
}
}
}
}
void join(const FindXExtremum &rhs) {
if(closerToExtremum(rhs.extrXPoint)) {
extrXPoint = rhs.extrXPoint;
}
}
point_t extremeXPoint() {
return extrXPoint;
}
private:
const pointVec_t &points;
const extremumType exType;
point_t extrXPoint;
bool closerToExtremum(const point_t &p) const {
switch(exType) {
case minX:
return p.x<extrXPoint.x; break;
case maxX:
return p.x>extrXPoint.x; break;
}
return false; // avoid warning
}
};
template <FindXExtremum::extremumType type>
point_t extremum(const pointVec_t &P) {
FindXExtremum fxBody(P, type);
tbb::parallel_reduce(range_t(0, P.size(), FindXExtremum::grainSize), fxBody);
return fxBody.extremeXPoint();
}
class SplitByCP_buf {
const pointVec_t &initialSet;
pointVec_t &reducedSet;
point_t p1, p2;
point_t farPoint;
double howFar;
public:
static const size_t grainSize = cfg::divideGrainSize;
SplitByCP_buf( point_t _p1, point_t _p2,
const pointVec_t &_initialSet, pointVec_t &_reducedSet)
: p1(_p1), p2(_p2),
initialSet(_initialSet), reducedSet(_reducedSet),
howFar(0), farPoint(p1) {}
SplitByCP_buf(SplitByCP_buf& sbcp, tbb::split)
: p1(sbcp.p1), p2(sbcp.p2),
initialSet(sbcp.initialSet), reducedSet(sbcp.reducedSet),
howFar(0), farPoint(p1) {}
void operator()(const range_t& range) {
const size_t i_end = range.end();
size_t j = 0;
double cp;
point_t tmp_vec[grainSize];
for(size_t i = range.begin(); i != i_end; ++i) {
if( (initialSet[i] != p1) && (initialSet[i] != p2) ) {
cp = util::cross_product(p1, p2, initialSet[i]);
if(cp>0) {
tmp_vec[j++] = initialSet[i];
if(cp>howFar) {
farPoint = initialSet[i];
howFar = cp;
}
}
}
}
appendVector(tmp_vec, j, reducedSet);
}
void join(const SplitByCP_buf& rhs) {
if(rhs.howFar>howFar) {
howFar = rhs.howFar;
farPoint = rhs.farPoint;
}
}
point_t farthestPoint() const {
return farPoint;
}
};
point_t divide(const pointVec_t &P, pointVec_t &P_reduced,
const point_t &p1, const point_t &p2) {
SplitByCP_buf sbcpb(p1, p2, P, P_reduced);
// Must use simple_partitioner (see the comment in initialize() above)
tbb::parallel_reduce(range_t(0, P.size(), SplitByCP_buf::grainSize),
sbcpb, tbb::simple_partitioner());
if(util::verbose) {
std::stringstream ss;
ss << P.size() << " nodes in bucket"<< ", "
<< "dividing by: [ " << p1 << ", " << p2 << " ], "
<< "farthest node: " << sbcpb.farthestPoint();
util::OUTPUT.push_back(ss.str());
}
return sbcpb.farthestPoint();
}
void divide_and_conquer(const pointVec_t &P, pointVec_t &H,
point_t p1, point_t p2) {
assert(P.size() >= 2);
pointVec_t P_reduced;
pointVec_t H1, H2;
point_t p_far = divide(P, P_reduced, p1, p2);
if (P_reduced.size()<2) {
H.push_back(p1);
appendVector(P_reduced, H);
}
else {
divide_and_conquer(P_reduced, H1, p1, p_far);
divide_and_conquer(P_reduced, H2, p_far, p2);
appendVector(H1, H);
appendVector(H2, H);
}
}
void quickhull(const pointVec_t &points, pointVec_t &hull) {
if (points.size() < 2) {
appendVector(points, hull);
return;
}
point_t p_maxx = extremum<FindXExtremum::maxX>(points);
point_t p_minx = extremum<FindXExtremum::minX>(points);
pointVec_t H;
divide_and_conquer(points, hull, p_maxx, p_minx);
divide_and_conquer(points, H, p_minx, p_maxx);
appendVector(H, hull);
}
int main(int argc, char* argv[]) {
utility::thread_number_range threads(utility::get_default_num_threads);
util::my_time_t tm_main_begin = util::gettime();
util::ParseInputArgs(argc, argv, threads);
pointVec_t points;
pointVec_t hull;
int nthreads;
points.reserve(cfg::numberOfPoints);
if(!util::silent) {
std::cout << "Starting TBB-buffered version of QUICK HULL algorithm" << std::endl;
}
for(nthreads=threads.first; nthreads<=threads.last; nthreads=threads.step(nthreads)) {
tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
points.clear();
util::my_time_t tm_init = util::gettime();
initialize(points);
util::my_time_t tm_start = util::gettime();
if(!util::silent) {
std::cout <<"Init time on "<<nthreads<<" threads: "<<util::time_diff(tm_init, tm_start)<<" Points in input: "<<points.size()<<std::endl;
}
tm_start = util::gettime();
quickhull(points, hull);
util::my_time_t tm_end = util::gettime();
if(!util::silent) {
std::cout <<"Time on "<<nthreads<<" threads: "<<util::time_diff(tm_start, tm_end)<<" Points in hull: "<<hull.size()<<std::endl;
}
hull.clear();
}
utility::report_elapsed_time(util::time_diff(tm_main_begin, util::gettime()));
return 0;
}

View File

@@ -0,0 +1,400 @@
<!DOCTYPE html>
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<meta charset="UTF-8">
<style>
::selection {
background: #b7ffb7;
}
::-moz-selection {
background: #b7ffb7;
}
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
width: 800px;
margin: 0 auto;
}
#banner {
/* Div for banner */
float:left;
margin: 0px;
margin-bottom: 10px;
width: 100%;
background-color: #0071C5;
z-index: 0;
}
#banner .logo {
/* Apply to logo in banner. Add as class to image tag. */
float: left;
margin-right: 20px;
margin-left: 20px;
margin-top: 15px;
padding-bottom: 5px;
}
h1 {
text-align: center;
font-size: 36px;
}
h1.title {
/* Add as class to H1 in banner */
font-family: "Intel Clear", Verdana, Arial, sans-serif;
font-weight:normal;
color: #FFFFFF;
font-size: 170%;
margin-right: 40px;
margin-left: 40px;
padding-right: 20px;
text-indent: 20px;
}
.h3-alike {
display:inline;
font-size: 1.17em;
font-weight: bold;
color: #0071C5;
}
h3 {
font-size: 1.17em;
font-weight: bold;
color: #0071C5;
}
.h4-alike {
display:inline;
font-size: 1.05em;
font-weight: bold;
}
pre {
font-family: "Consolas", Monaco, monospace;
font-size:small;
background: #fafafa;
margin: 0;
padding-left:20px;
}
#footer {
font-size: small;
}
code {
font-family: "Consolas", Monaco, monospace;
}
.code-block
{
padding-left:20px;
}
.changes {
margin: 1em 0;
}
.changes input:active {
position: relative;
top: 1px;
}
.changes input:hover:after {
padding-left: 16px;
font-size: 10px;
content: 'More';
}
.changes input:checked:hover:after {
content: 'Less';
}
.changes input + .show-hide {
display: none;
}
.changes input:checked + .show-hide {
display: block;
}
ul {
margin: 0;
padding: 0.5em 0 0.5em 2.5em;
}
ul li {
margin-bottom: 3px;
}
ul li:last-child {
margin-bottom: 0;
}
.disc {
list-style-type:disc
}
.circ {
list-style-type:circle
}
.single {
padding: 0 0.5em;
}
/* ------------------------------------------------- */
/* Table styles */
table{
margin-bottom:5pt;
border-collapse:collapse;
margin-left:0px;
margin-top:0.3em;
font-size:10pt;
}
tr{
vertical-align:top;
}
th,
th h3{
padding:4px;
text-align:left;
background-color:#0071C5;
font-weight:bold;
margin-top:1px;
margin-bottom:0;
color:#FFFFFF;
font-size:10pt;
vertical-align:middle;
}
th{
border:1px #dddddd solid;
padding-top:2px;
padding-bottom:0px;
padding-right:3px;
padding-left:3px;
}
td{
border:1px #dddddd solid;
vertical-align:top;
font-size:100%;
text-align:left;
margin-bottom:0;
}
td,
td p{
margin-top:0;
margin-left:0;
text-align:left;
font-size:inherit;
line-height:120%;
}
td p{
margin-bottom:0;
padding-top:5px;
padding-bottom:5px;
padding-right:5px;
padding-left:1px;
}
.noborder{
border:0px none;
}
.noborder1stcol{
border:0px none;
padding-left:0pt;
}
td ol{
font-size:inherit;
margin-left:28px;
}
td ul{
font-size:inherit;
margin-left:24px;
}
.DefListTbl{
width:90%;
margin-left:-3pt;
}
.syntaxdiagramtbl{
margin-left:-3pt;
}
.sdtbl{
}
.sdrow{
}
.sdtblp{
border:0px none;
font-size:inherit;
line-height:120%;
margin-bottom:0;
padding-bottom:0px;
padding-top:5px;
padding-left:0px;
padding-right:5px;
vertical-align:top;
}
.idepara, .ide_para{
border:0px none;
font-size:inherit;
line-height:120%;
margin-bottom:0;
padding-bottom:0px;
padding-top:5px;
padding-left:0px;
padding-right:5px;
vertical-align:top;
}
.specs {
border-collapse:collapse;
}
.specs td, .specs th {
font-size: 14px;
}
.specs td {
border: 1px solid black;
}
.specs td td, .specs td th {
border: none;
}
.specs td, .specs td td, .specs td th {
padding: 0 0.2em 0.2em;
text-align: center;
}
.specs td tr:last-child td,
.specs td tr:last-child th {
padding: 0 0.2em;
}
.serial-time {
}
.modified-time {
width: 6.5em;
}
.compiler {
}
.comp-opt {
}
.sys-specs {
width: 18em;
}
.note {
font-size:small;
font-style: italic;
}
</style>
<title>Intel&reg; Threading Building Blocks. Convex_hull sample</title>
</head>
<body>
<div id="banner">
<img class="logo" src="data:image/png;base64,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
9Or1LzUmVVz+HJXDAAAAAElFTkSuQmCC">
<h1 class="title">Intel&reg; Threading Building Blocks.<br>Convex_hull sample</h1>
</div>
<p>
Parallel version of convex hull algorithm (quick hull).
</p>
<div class="changes">
<div class="h3-alike">System Requirements</div>
<input type="checkbox">
<div class="show-hide">
<p>
For the most up to date system requirements, see the <a href="http://software.intel.com/en-us/articles/intel-threading-building-blocks-release-notes">release notes.</a>
</p>
</div>
</div>
<div class="changes">
<div class="h3-alike">Files</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<dl>
<dt><a href="convex_hull_sample.cpp">convex_hull_sample.cpp</a>
<dd>Source code for parallel version of the example which uses parallel_reduce, parallel_for and concurrent_vector.
<dt><a href="convex_hull_bench.cpp">convex_hull_bench.cpp</a>
<dd>Source code for the version of the example that compares serial and parallel buffered and unbuffered implementations.
<dt><a href="convex_hull.h">convex_hull.h</a>
<dd>Include file for the example.
<dt><a href="Makefile">Makefile</a>
<dd>Makefile for building the example.
</dl>
</div>
</div>
<div class="changes">
<div class="h3-alike">Directories</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<dl>
<dt><a href="msvs/">msvs</a>
<dd>Contains Microsoft* Visual Studio* workspace for building and running the example (Windows* systems only).
<dt><a href="xcode/">xcode</a>
<dd>Contains Xcode* IDE workspace for building and running the example (macOS* systems only).
</dl>
<p>For information about the minimum supported version of IDE, see <a href="http://software.intel.com/en-us/articles/intel-threading-building-blocks-release-notes">release notes.</a></p>
</div>
</div>
<div class="changes">
<div class="h3-alike">Build instructions</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<p>General build directions can be found <a href="../../index.html">here</a>.</p>
</div>
</div>
<div class="changes">
<div class="h3-alike">Usage</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<dl>
<dt><tt>convex_hull_sample [<i>S</i>] [<i>M</i>[:<i>N</i>]] [-v]</tt>
<dd><i>S</i> is the number of points (problem size).
<i>M:N</i> are a range of numbers of threads to be used.
Use the -v option to turn on verbose output.
<dt>To run a short version of this example, e.g., for use with Intel&reg; Threading Tools:
<dd>Build a <i>debug</i> version of the example
(see the <a href="../../index.html">build instructions</a>).
<br>Run it with a small problem size and the desired number of threads, e.g., <tt>convex_hull_sample&nbsp;4&nbsp;500000</tt>.
</dl>
</div>
</div>
<br>
<a href="../index.html">Up to parent directory</a>
<hr>
<div class="changes">
<div class="h3-alike">Legal Information</div>
<input type="checkbox">
<div class="show-hide">
<p>
Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries.
<br>* Other names and brands may be claimed as the property of others.
<br>&copy; 2020, Intel Corporation
</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,350 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
A146114A0B94631F000C6B18 /* convex_hull_bench.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14611490B94631F000C6B18 /* convex_hull_bench.cpp */; };
A1F593A60B8F042A00073279 /* convex_hull_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* convex_hull_sample.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
C3C5895A218B677B00DAC94C /* PBXBuildRule */ = {
isa = PBXBuildRule;
compilerSpec = com.intel.compilers.icc.latest;
fileType = sourcecode.cpp;
isEditable = 1;
outputFiles = (
);
script = "# Type a script or drag a script file from your workspace to insert its path.\n";
};
/* End PBXBuildRule section */
/* Begin PBXCopyFilesBuildPhase section */
8DD76F690486A84900D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 12;
dstPath = "";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
A1F594F40B8F4E7700073279 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
A14611490B94631F000C6B18 /* convex_hull_bench.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = convex_hull_bench.cpp; path = ../convex_hull_bench.cpp; sourceTree = SOURCE_ROOT; };
A146114C0B9463CB000C6B18 /* convex_hull.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = convex_hull.h; path = ../convex_hull.h; sourceTree = SOURCE_ROOT; };
A1F593A50B8F042A00073279 /* convex_hull_sample.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = convex_hull_sample.cpp; path = ../convex_hull_sample.cpp; sourceTree = SOURCE_ROOT; };
A1F594EB0B8F4B5600073279 /* convex_hull_bench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = convex_hull_bench; sourceTree = BUILT_PRODUCTS_DIR; };
A1F594FA0B8F4EE000073279 /* convex_hull_sample */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = convex_hull_sample; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DD76F660486A84900D96B5E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
A1F594E90B8F4B5600073279 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* convex_hull */ = {
isa = PBXGroup;
children = (
08FB7795FE84155DC02AAC07 /* Source */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
name = convex_hull;
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
A146114C0B9463CB000C6B18 /* convex_hull.h */,
A14611490B94631F000C6B18 /* convex_hull_bench.cpp */,
A1F593A50B8F042A00073279 /* convex_hull_sample.cpp */,
);
name = Source;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
A1F594EB0B8F4B5600073279 /* convex_hull_bench */,
A1F594FA0B8F4EE000073279 /* convex_hull_sample */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
8DD76F620486A84900D96B5E /* convex_hull_sample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "convex_hull_sample" */;
buildPhases = (
8DD76F640486A84900D96B5E /* Sources */,
8DD76F660486A84900D96B5E /* Frameworks */,
8DD76F690486A84900D96B5E /* CopyFiles */,
);
buildRules = (
C3C5895A218B677B00DAC94C /* PBXBuildRule */,
);
dependencies = (
);
name = convex_hull_sample;
productInstallPath = "$(HOME)/bin";
productName = convex_hull;
productReference = A1F594FA0B8F4EE000073279 /* convex_hull_sample */;
productType = "com.apple.product-type.tool";
};
A1F594EA0B8F4B5600073279 /* convex_hull_bench */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1F594EE0B8F4B8200073279 /* Build configuration list for PBXNativeTarget "convex_hull_bench" */;
buildPhases = (
A1F594E80B8F4B5600073279 /* Sources */,
A1F594E90B8F4B5600073279 /* Frameworks */,
A1F594F40B8F4E7700073279 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = convex_hull_bench;
productName = convex_hull_bench;
productReference = A1F594EB0B8F4B5600073279 /* convex_hull_bench */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1000;
};
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "convex_hull" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* convex_hull */;
projectDirPath = "";
projectRoot = "";
targets = (
8DD76F620486A84900D96B5E /* convex_hull_sample */,
A1F594EA0B8F4B5600073279 /* convex_hull_bench */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
8DD76F640486A84900D96B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1F593A60B8F042A00073279 /* convex_hull_sample.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1F594E80B8F4B5600073279 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A146114A0B94631F000C6B18 /* convex_hull_bench.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
A1F593C60B8F0E6E00073279 /* Debug64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = "";
HEADER_SEARCH_PATHS = "$(inherited)";
ICC_CXX_LANG_DIALECT = "c++11";
INSTALL_PATH = "$(HOME)/bin";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = convex_hull_sample;
ZERO_LINK = NO;
};
name = Debug64;
};
A1F593C70B8F0E6E00073279 /* Release64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_VERSION = "";
HEADER_SEARCH_PATHS = "$(inherited)";
ICC_CXX_LANG_DIALECT = "c++11";
INSTALL_PATH = "$(HOME)/bin";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = convex_hull_sample;
ZERO_LINK = NO;
};
name = Release64;
};
A1F593C80B8F0E6E00073279 /* Debug64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ENABLE_TESTABILITY = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_MODEL_TUNING = "";
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(TBBROOT)/include",
/opt/intel/tbb/include,
);
ICC_CXX_LANG_DIALECT = "c++11";
LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
LIBRARY_SEARCH_PATHS = (
"$(TBBROOT)/lib",
/opt/intel/tbb/lib,
);
MACOSX_DEPLOYMENT_TARGET = 10.11;
ONLY_ACTIVE_ARCH = YES;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-m64",
);
OTHER_LDFLAGS = (
"-m64",
"-ltbb_debug",
);
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
SYMROOT = "/tmp/tbb-$(USER)";
VALID_ARCHS = x86_64;
};
name = Debug64;
};
A1F593C90B8F0E6E00073279 /* Release64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_ENABLE_CPP_RTTI = YES;
GCC_MODEL_TUNING = "";
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(TBBROOT)/include",
/opt/intel/tbb/include,
);
ICC_CXX_LANG_DIALECT = "c++11";
LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
LIBRARY_SEARCH_PATHS = (
"$(TBBROOT)/lib",
/opt/intel/tbb/lib,
);
MACOSX_DEPLOYMENT_TARGET = 10.11;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-m64",
);
OTHER_LDFLAGS = (
"-m64",
"-ltbb",
);
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
SYMROOT = "/tmp/tbb-$(USER)";
VALID_ARCHS = x86_64;
};
name = Release64;
};
A1F594F00B8F4B8200073279 /* Debug64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = "";
HEADER_SEARCH_PATHS = "$(inherited)";
INSTALL_PATH = "$(HOME)/bin";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = convex_hull_bench;
ZERO_LINK = NO;
};
name = Debug64;
};
A1F594F20B8F4B8200073279 /* Release64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_VERSION = "";
HEADER_SEARCH_PATHS = "$(inherited)";
INSTALL_PATH = "$(HOME)/bin";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = convex_hull_bench;
ZERO_LINK = NO;
};
name = Release64;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "convex_hull_sample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1F593C60B8F0E6E00073279 /* Debug64 */,
A1F593C70B8F0E6E00073279 /* Release64 */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release64;
};
1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "convex_hull" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1F593C80B8F0E6E00073279 /* Debug64 */,
A1F593C90B8F0E6E00073279 /* Release64 */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release64;
};
A1F594EE0B8F4B8200073279 /* Build configuration list for PBXNativeTarget "convex_hull_bench" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1F594F00B8F4B8200073279 /* Debug64 */,
A1F594F20B8F4B8200073279 /* Release64 */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release64;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

View File

@@ -0,0 +1,346 @@
<!DOCTYPE html>
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<meta charset="UTF-8">
<style>
::selection {
background: #b7ffb7;
}
::-moz-selection {
background: #b7ffb7;
}
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
width: 800px;
margin: 0 auto;
}
#banner {
/* Div for banner */
float:left;
margin: 0px;
margin-bottom: 10px;
width: 100%;
background-color: #0071C5;
z-index: 0;
}
#banner .logo {
/* Apply to logo in banner. Add as class to image tag. */
float: left;
margin-right: 20px;
margin-left: 20px;
margin-top: 15px;
padding-bottom: 5px;
}
h1 {
text-align: center;
font-size: 36px;
}
h1.title {
/* Add as class to H1 in banner */
font-family: "Intel Clear", Verdana, Arial, sans-serif;
font-weight:normal;
color: #FFFFFF;
font-size: 170%;
margin-right: 40px;
margin-left: 40px;
padding-right: 20px;
text-indent: 20px;
}
.h3-alike {
display:inline;
font-size: 1.17em;
font-weight: bold;
color: #0071C5;
}
h3 {
font-size: 1.17em;
font-weight: bold;
color: #0071C5;
}
.h4-alike {
display:inline;
font-size: 1.05em;
font-weight: bold;
}
pre {
font-family: "Consolas", Monaco, monospace;
font-size:small;
background: #fafafa;
margin: 0;
padding-left:20px;
}
#footer {
font-size: small;
}
code {
font-family: "Consolas", Monaco, monospace;
}
.code-block
{
padding-left:20px;
}
.changes {
margin: 1em 0;
}
.changes input:active {
position: relative;
top: 1px;
}
.changes input:hover:after {
padding-left: 16px;
font-size: 10px;
content: 'More';
}
.changes input:checked:hover:after {
content: 'Less';
}
.changes input + .show-hide {
display: none;
}
.changes input:checked + .show-hide {
display: block;
}
ul {
margin: 0;
padding: 0.5em 0 0.5em 2.5em;
}
ul li {
margin-bottom: 3px;
}
ul li:last-child {
margin-bottom: 0;
}
.disc {
list-style-type:disc
}
.circ {
list-style-type:circle
}
.single {
padding: 0 0.5em;
}
/* ------------------------------------------------- */
/* Table styles */
table{
margin-bottom:5pt;
border-collapse:collapse;
margin-left:0px;
margin-top:0.3em;
font-size:10pt;
}
tr{
vertical-align:top;
}
th,
th h3{
padding:4px;
text-align:left;
background-color:#0071C5;
font-weight:bold;
margin-top:1px;
margin-bottom:0;
color:#FFFFFF;
font-size:10pt;
vertical-align:middle;
}
th{
border:1px #dddddd solid;
padding-top:2px;
padding-bottom:0px;
padding-right:3px;
padding-left:3px;
}
td{
border:1px #dddddd solid;
vertical-align:top;
font-size:100%;
text-align:left;
margin-bottom:0;
}
td,
td p{
margin-top:0;
margin-left:0;
text-align:left;
font-size:inherit;
line-height:120%;
}
td p{
margin-bottom:0;
padding-top:5px;
padding-bottom:5px;
padding-right:5px;
padding-left:1px;
}
.noborder{
border:0px none;
}
.noborder1stcol{
border:0px none;
padding-left:0pt;
}
td ol{
font-size:inherit;
margin-left:28px;
}
td ul{
font-size:inherit;
margin-left:24px;
}
.DefListTbl{
width:90%;
margin-left:-3pt;
}
.syntaxdiagramtbl{
margin-left:-3pt;
}
.sdtbl{
}
.sdrow{
}
.sdtblp{
border:0px none;
font-size:inherit;
line-height:120%;
margin-bottom:0;
padding-bottom:0px;
padding-top:5px;
padding-left:0px;
padding-right:5px;
vertical-align:top;
}
.idepara, .ide_para{
border:0px none;
font-size:inherit;
line-height:120%;
margin-bottom:0;
padding-bottom:0px;
padding-top:5px;
padding-left:0px;
padding-right:5px;
vertical-align:top;
}
.specs {
border-collapse:collapse;
}
.specs td, .specs th {
font-size: 14px;
}
.specs td {
border: 1px solid black;
}
.specs td td, .specs td th {
border: none;
}
.specs td, .specs td td, .specs td th {
padding: 0 0.2em 0.2em;
text-align: center;
}
.specs td tr:last-child td,
.specs td tr:last-child th {
padding: 0 0.2em;
}
.serial-time {
}
.modified-time {
width: 6.5em;
}
.compiler {
}
.comp-opt {
}
.sys-specs {
width: 18em;
}
.note {
font-size:small;
font-style: italic;
}
</style>
<title>Intel&reg; Threading Building Blocks. Samples on parallel_reduce</title>
</head>
<body>
<div id="banner">
<img class="logo" src="data:image/png;base64,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
9Or1LzUmVVz+HJXDAAAAAElFTkSuQmCC">
<h1 class="title">Intel&reg; Threading Building Blocks.<br>Samples on <code>parallel_reduce</code> algorithm</h1>
</div>
<p>
This directory has examples of the <code>parallel_reduce</code> algorithm.
</p>
<div class="changes">
<div class="h3-alike">Directories</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<dl>
<dt><a href="convex_hull/readme.html">convex_hull</a>
<dd>Parallel version of convex hull algorithm (quick hull).
<dt><a href="primes/readme.html">primes</a>
<dd>Parallel version of the Sieve of Eratosthenes.
</dl>
</div>
</div>
<br>
<a href="../index.html">Up to parent directory</a>
<hr>
<div class="changes">
<div class="h3-alike">Legal Information:</div>
<input type="checkbox">
<div class="show-hide">
<p>
Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries.
<br>* Other names and brands may be claimed as the property of others.
<br>&copy; 2020, Intel Corporation
</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,48 @@
# Copyright (c) 2005-2020 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Common Makefile that builds and runs example.
# Just specify your program basename
PROG=Primes
ARGS=0:auto
PERF_RUN_ARGS=silent auto 1000000000 1000 20
# Trying to find if icl.exe is set
CXX1 = $(TBB_CXX)-
CXX2 = $(CXX1:icl.exe-=icl.exe)
CXX = $(CXX2:-=cl.exe)
# The C++ compiler options
MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 $(CXXFLAGS)
MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS)
all: release test
release: compiler_check
$(CXX) main.cpp primes.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe
debug: compiler_check
$(CXX) main.cpp primes.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe
clean:
@cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest
test:
$(PROG) $(ARGS)
perf_build: release
perf_run:
$(PROG) $(PERF_RUN_ARGS)
compiler_check:
@echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly"
@cmd.exe /C del compiler_test

View File

@@ -0,0 +1,106 @@
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "primes.h"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <utility>
#include <iostream>
#include <sstream>
#include "tbb/tick_count.h"
#include "../../common/utility/utility.h"
struct RunOptions{
//! NumberType of threads to use.
utility::thread_number_range threads;
//whether to suppress additional output
bool silentFlag;
//
NumberType n;
//! Grain size parameter
NumberType grainSize;
// number of time to repeat calculation
NumberType repeatNumber;
RunOptions(utility::thread_number_range threads_, NumberType grainSize_, NumberType n_, bool silentFlag_, NumberType repeatNumber_)
: threads(threads_), silentFlag(silentFlag_), n(n_), grainSize(grainSize_), repeatNumber(repeatNumber_)
{}
};
//! Parse the command line.
static RunOptions ParseCommandLine( int argc, const char* argv[] ) {
utility::thread_number_range threads( utility::get_default_num_threads, 0, utility::get_default_num_threads() );
NumberType grainSize = 1000;
bool silent = false;
NumberType number = 100000000;
NumberType repeatNumber = 1;
utility::parse_cli_arguments(argc,argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.positional_arg(threads,"n-of-threads",utility::thread_number_range_desc)
.positional_arg(number,"number","upper bound of range to search primes in, must be a positive integer")
.positional_arg(grainSize,"grain-size","must be a positive integer")
.positional_arg(repeatNumber,"n-of-repeats","repeat the calculation this number of times, must be a positive integer")
.arg(silent,"silent","no output except elapsed time")
);
RunOptions options(threads,grainSize, number, silent, repeatNumber);
return options;
}
int main( int argc, const char* argv[] ) {
tbb::tick_count mainBeginMark = tbb::tick_count::now();
RunOptions options =ParseCommandLine(argc,argv);
// Try different numbers of threads
for( int p=options.threads.first; p<=options.threads.last; p=options.threads.step(p) ) {
for (NumberType i=0; i<options.repeatNumber;++i){
tbb::tick_count iterationBeginMark = tbb::tick_count::now();
NumberType count = 0;
NumberType n = options.n;
if( p==0 ) {
#if __TBB_MIC_OFFLOAD
#pragma offload target(mic) in(n) out(count)
#endif // __TBB_MIC_OFFLOAD
count = SerialCountPrimes(n);
} else {
NumberType grainSize = options.grainSize;
#if __TBB_MIC_OFFLOAD
#pragma offload target(mic) in(n, p, grainSize) out(count)
#endif // __TBB_MIC_OFFLOAD
count = ParallelCountPrimes(n, p, grainSize);
}
tbb::tick_count iterationEndMark = tbb::tick_count::now();
if (!options.silentFlag){
std::cout
<<"#primes from [2.." <<options.n<<"] = " << count
<<" ("<<(iterationEndMark-iterationBeginMark).seconds()<< " sec with "
;
if( 0 != p )
std::cout<<p<<"-way parallelism";
else
std::cout<<"serial code";
std::cout<<")\n" ;
}
}
}
utility::report_elapsed_time((tbb::tick_count::now()-mainBeginMark).seconds());
return 0;
}

View File

@@ -0,0 +1,304 @@
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Example program that computes number of prime numbers up to n,
// where n is a command line argument. The algorithm here is a
// fairly efficient version of the sieve of Eratosthenes.
// The parallel version demonstrates how to use parallel_reduce,
// and in particular how to exploit lazy splitting.
#include "primes.h"
#if __TBB_MIC_OFFLOAD
#pragma offload_attribute (target(mic))
#endif // __TBB_MIC_OFFLOAD
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <cstdlib>
#include <cctype>
#include "tbb/parallel_reduce.h"
using namespace std;
//! If true, then print primes on stdout.
static bool printPrimes = false;
class Multiples {
inline NumberType strike( NumberType start, NumberType limit, NumberType stride ) {
// Hoist "my_is_composite" into register for sake of speed.
bool* is_composite = my_is_composite;
assert( stride>=2 );
for( ;start<limit; start+=stride )
is_composite[start] = true;
return start;
}
//! Window into conceptual sieve
bool* my_is_composite;
//! Indexes into window
/** my_striker[k] is an index into my_composite corresponding to
an odd multiple multiple of my_factor[k]. */
NumberType* my_striker;
//! Prime numbers less than m.
NumberType* my_factor;
public:
//! NumberType of factors in my_factor.
NumberType n_factor;
NumberType m;
Multiples( NumberType n ) {
m = NumberType(sqrt(double(n)));
// Round up to even
m += m&1;
my_is_composite = new bool[m/2];
my_striker = new NumberType[m/2];
my_factor = new NumberType[m/2];
n_factor = 0;
memset( my_is_composite, 0, m/2 );
for( NumberType i=3; i<m; i+=2 ) {
if( !my_is_composite[i/2] ) {
if( printPrimes )
printf("%d\n",(int)i);
my_striker[n_factor] = strike( i/2, m/2, i );
my_factor[n_factor++] = i;
}
}
}
//! Find primes in range [start,window_size), advancing my_striker as we go.
/** Returns number of primes found. */
NumberType find_primes_in_window( NumberType start, NumberType window_size ) {
bool* is_composite = my_is_composite;
memset( is_composite, 0, window_size/2 );
for( size_t k=0; k<n_factor; ++k )
my_striker[k] = strike( my_striker[k]-m/2, window_size/2, my_factor[k] );
NumberType count = 0;
for( NumberType k=0; k<window_size/2; ++k ) {
if( !is_composite[k] ) {
if( printPrimes )
printf("%ld\n",long(start+2*k+1));
++count;
}
}
return count;
}
~Multiples() {
delete[] my_factor;
delete[] my_striker;
delete[] my_is_composite;
}
//------------------------------------------------------------------------
// Begin extra members required by parallel version
//------------------------------------------------------------------------
// Splitting constructor
Multiples( const Multiples& f, tbb::split ) :
n_factor(f.n_factor),
m(f.m),
my_is_composite(NULL),
my_striker(NULL),
my_factor(f.my_factor)
{}
bool is_initialized() const {
return my_is_composite!=NULL;
}
void initialize( NumberType start ) {
assert( start>=1 );
my_is_composite = new bool[m/2];
my_striker = new NumberType[m/2];
for( size_t k=0; k<n_factor; ++k ) {
NumberType f = my_factor[k];
NumberType p = (start-1)/f*f % m;
my_striker[k] = (p&1 ? p+2*f : p+f)/2;
assert( m/2<=my_striker[k] );
}
}
// Move other to *this.
void move( Multiples& other ) {
// The swap moves the contents of other to *this and causes the old contents
// of *this to be deleted later when other is destroyed.
std::swap( my_striker, other.my_striker );
std::swap( my_is_composite, other.my_is_composite );
// other.my_factor is a shared pointer that was copied by the splitting constructor.
// Set it to NULL to prevent premature deletion by the destructor of ~other.
assert(my_factor==other.my_factor);
other.my_factor = NULL;
}
//------------------------------------------------------------------------
// End extra methods required by parallel version
//------------------------------------------------------------------------
};
//! Count number of primes between 0 and n
/** This is the serial version. */
NumberType SerialCountPrimes( NumberType n ) {
// Two is special case
NumberType count = n>=2;
if( n>=3 ) {
Multiples multiples(n);
count += multiples.n_factor;
if( printPrimes )
printf("---\n");
NumberType window_size = multiples.m;
for( NumberType j=multiples.m; j<=n; j+=window_size ) {
if( j+window_size>n+1 )
window_size = n+1-j;
count += multiples.find_primes_in_window( j, window_size );
}
}
return count;
}
//! Range of a sieve window.
class SieveRange {
//! Width of full-size window into sieve.
const NumberType my_stride;
//! Always multiple of my_stride
NumberType my_begin;
//! One past last number in window.
NumberType my_end;
//! Width above which it is worth forking.
const NumberType my_grainsize;
bool assert_okay() const {
assert( my_begin%my_stride==0 );
assert( my_begin<=my_end );
assert( my_stride<=my_grainsize );
return true;
}
public:
//------------------------------------------------------------------------
// Begin signatures required by parallel_reduce
//------------------------------------------------------------------------
bool is_divisible() const {return my_end-my_begin>my_grainsize;}
bool empty() const {return my_end<=my_begin;}
SieveRange( SieveRange& r, tbb::split ) :
my_stride(r.my_stride),
my_grainsize(r.my_grainsize),
my_end(r.my_end)
{
assert( r.is_divisible() );
assert( r.assert_okay() );
NumberType middle = r.my_begin + (r.my_end-r.my_begin+r.my_stride-1)/2;
middle = middle/my_stride*my_stride;
my_begin = middle;
r.my_end = middle;
assert( assert_okay() );
assert( r.assert_okay() );
}
//------------------------------------------------------------------------
// End of signatures required by parallel_reduce
//------------------------------------------------------------------------
NumberType begin() const {return my_begin;}
NumberType end() const {return my_end;}
SieveRange( NumberType begin, NumberType end, NumberType stride, NumberType grainsize ) :
my_begin(begin),
my_end(end),
my_stride(stride),
my_grainsize(grainsize<stride?stride:grainsize)
{
assert( assert_okay() );
}
};
//! Loop body for parallel_reduce.
/** parallel_reduce splits the sieve into subsieves.
Each subsieve handles a subrange of [0..n]. */
class Sieve {
public:
//! Prime Multiples to consider, and working storage for this subsieve.
::Multiples multiples;
//! NumberType of primes found so far by this subsieve.
NumberType count;
//! Construct Sieve for counting primes in [0..n].
Sieve( NumberType n ) :
multiples(n),
count(0)
{}
//------------------------------------------------------------------------
// Begin signatures required by parallel_reduce
//------------------------------------------------------------------------
void operator()( const SieveRange& r ) {
NumberType m = multiples.m;
if( multiples.is_initialized() ) {
// Simply reuse "Multiples" structure from previous window
// This works because parallel_reduce always applies
// *this from left to right.
} else {
// Need to initialize "Multiples" because *this is a forked copy
// that needs to be set up to start at r.begin().
multiples.initialize( r.begin() );
}
NumberType window_size = m;
for( NumberType j=r.begin(); j<r.end(); j+=window_size ) {
assert( j%multiples.m==0 );
if( j+window_size>r.end() )
window_size = r.end()-j;
count += multiples.find_primes_in_window( j, window_size );
}
}
void join( Sieve& other ) {
count += other.count;
// Final value of multiples needs to final value of other multiples,
// so that *this can correctly process next window to right.
multiples.move( other.multiples );
}
Sieve( Sieve& other, tbb::split ) :
multiples(other.multiples,tbb::split()),
count(0)
{}
//------------------------------------------------------------------------
// End of signatures required by parallel_reduce
//------------------------------------------------------------------------
};
//! Count number of primes between 0 and n
/** This is the parallel version. */
NumberType ParallelCountPrimes( NumberType n , int number_of_threads, NumberType grain_size ) {
tbb::global_control c(tbb::global_control::max_allowed_parallelism, number_of_threads);
// Two is special case
NumberType count = n>=2;
if( n>=3 ) {
Sieve s(n);
count += s.multiples.n_factor;
if( printPrimes )
printf("---\n");
using namespace tbb;
// Explicit grain size and simple_partitioner() used here instead of automatic grainsize
// determination because we want SieveRange to be decomposed down to grainSize or smaller.
// Doing so improves odds that the working set fits in cache when evaluating Sieve::operator().
parallel_reduce( SieveRange( s.multiples.m, n, s.multiples.m, grain_size ), s, simple_partitioner() );
count += s.count;
}
return count;
}

View File

@@ -0,0 +1,40 @@
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef PRIMES_H_
#define PRIMES_H_
#if __TBB_MIC_OFFLOAD
#pragma offload_attribute (push,target(mic))
#endif // __TBB_MIC_OFFLOAD
#include "../../common/utility/get_default_num_threads.h"
#include <cstddef>
typedef std::size_t NumberType;
//! Count number of primes between 0 and n
/** This is the serial version. */
NumberType SerialCountPrimes( NumberType n);
//! Count number of primes between 0 and n
/** This is the parallel version. */
NumberType ParallelCountPrimes( NumberType n, int numberOfThreads= utility::get_default_num_threads(), NumberType grainSize = 1000);
#if __TBB_MIC_OFFLOAD
#pragma offload_attribute (pop)
#endif // __TBB_MIC_OFFLOAD
#endif /* PRIMES_H_ */

View File

@@ -0,0 +1,407 @@
<!DOCTYPE html>
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<meta charset="UTF-8">
<style>
::selection {
background: #b7ffb7;
}
::-moz-selection {
background: #b7ffb7;
}
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
width: 800px;
margin: 0 auto;
}
#banner {
/* Div for banner */
float:left;
margin: 0px;
margin-bottom: 10px;
width: 100%;
background-color: #0071C5;
z-index: 0;
}
#banner .logo {
/* Apply to logo in banner. Add as class to image tag. */
float: left;
margin-right: 20px;
margin-left: 20px;
margin-top: 15px;
padding-bottom: 5px;
}
h1 {
text-align: center;
font-size: 36px;
}
h1.title {
/* Add as class to H1 in banner */
font-family: "Intel Clear", Verdana, Arial, sans-serif;
font-weight:normal;
color: #FFFFFF;
font-size: 170%;
margin-right: 40px;
margin-left: 40px;
padding-right: 20px;
text-indent: 20px;
}
.h3-alike {
display:inline;
font-size: 1.17em;
font-weight: bold;
color: #0071C5;
}
h3 {
font-size: 1.17em;
font-weight: bold;
color: #0071C5;
}
.h4-alike {
display:inline;
font-size: 1.05em;
font-weight: bold;
}
pre {
font-family: "Consolas", Monaco, monospace;
font-size:small;
background: #fafafa;
margin: 0;
padding-left:20px;
}
#footer {
font-size: small;
}
code {
font-family: "Consolas", Monaco, monospace;
}
.code-block
{
padding-left:20px;
}
.changes {
margin: 1em 0;
}
.changes input:active {
position: relative;
top: 1px;
}
.changes input:hover:after {
padding-left: 16px;
font-size: 10px;
content: 'More';
}
.changes input:checked:hover:after {
content: 'Less';
}
.changes input + .show-hide {
display: none;
}
.changes input:checked + .show-hide {
display: block;
}
ul {
margin: 0;
padding: 0.5em 0 0.5em 2.5em;
}
ul li {
margin-bottom: 3px;
}
ul li:last-child {
margin-bottom: 0;
}
.disc {
list-style-type:disc
}
.circ {
list-style-type:circle
}
.single {
padding: 0 0.5em;
}
/* ------------------------------------------------- */
/* Table styles */
table{
margin-bottom:5pt;
border-collapse:collapse;
margin-left:0px;
margin-top:0.3em;
font-size:10pt;
}
tr{
vertical-align:top;
}
th,
th h3{
padding:4px;
text-align:left;
background-color:#0071C5;
font-weight:bold;
margin-top:1px;
margin-bottom:0;
color:#FFFFFF;
font-size:10pt;
vertical-align:middle;
}
th{
border:1px #dddddd solid;
padding-top:2px;
padding-bottom:0px;
padding-right:3px;
padding-left:3px;
}
td{
border:1px #dddddd solid;
vertical-align:top;
font-size:100%;
text-align:left;
margin-bottom:0;
}
td,
td p{
margin-top:0;
margin-left:0;
text-align:left;
font-size:inherit;
line-height:120%;
}
td p{
margin-bottom:0;
padding-top:5px;
padding-bottom:5px;
padding-right:5px;
padding-left:1px;
}
.noborder{
border:0px none;
}
.noborder1stcol{
border:0px none;
padding-left:0pt;
}
td ol{
font-size:inherit;
margin-left:28px;
}
td ul{
font-size:inherit;
margin-left:24px;
}
.DefListTbl{
width:90%;
margin-left:-3pt;
}
.syntaxdiagramtbl{
margin-left:-3pt;
}
.sdtbl{
}
.sdrow{
}
.sdtblp{
border:0px none;
font-size:inherit;
line-height:120%;
margin-bottom:0;
padding-bottom:0px;
padding-top:5px;
padding-left:0px;
padding-right:5px;
vertical-align:top;
}
.idepara, .ide_para{
border:0px none;
font-size:inherit;
line-height:120%;
margin-bottom:0;
padding-bottom:0px;
padding-top:5px;
padding-left:0px;
padding-right:5px;
vertical-align:top;
}
.specs {
border-collapse:collapse;
}
.specs td, .specs th {
font-size: 14px;
}
.specs td {
border: 1px solid black;
}
.specs td td, .specs td th {
border: none;
}
.specs td, .specs td td, .specs td th {
padding: 0 0.2em 0.2em;
text-align: center;
}
.specs td tr:last-child td,
.specs td tr:last-child th {
padding: 0 0.2em;
}
.serial-time {
}
.modified-time {
width: 6.5em;
}
.compiler {
}
.comp-opt {
}
.sys-specs {
width: 18em;
}
.note {
font-size:small;
font-style: italic;
}
</style>
<title>Intel&reg; Threading Building Blocks. Primes sample</title>
</head>
<body>
<div id="banner">
<img class="logo" src="data:image/png;base64,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
9Or1LzUmVVz+HJXDAAAAAElFTkSuQmCC">
<h1 class="title">Intel&reg; Threading Building Blocks.<br>Primes sample</h1>
</div>
<p>
Parallel version of the Sieve of Eratosthenes.
<br><br>
The example can be built in the offload version to run on Intel&reg; Many Integrated Core (Intel&reg; MIC) Architecture based coprocessor (see <a href="../../index.html">build instructions</a>).
</p>
<div class="changes">
<div class="h3-alike">System Requirements</div>
<input type="checkbox">
<div class="show-hide">
<p>
For the most up to date system requirements, see the <a href="http://software.intel.com/en-us/articles/intel-threading-building-blocks-release-notes">release notes.</a>
</p>
</div>
</div>
<div class="changes">
<div class="h3-alike">Files</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<dl>
<dt><a href="main.cpp">main.cpp</a>
<dd>Main program which parses command line options and runs the algorithm with different numbers of threads.
<dt><a href="primes.h">primes.h</a>
<dd>The Sieve of Eratosthenes interface.
<dt><a href="primes.cpp">primes.cpp</a>
<dd>The Sieve of Eratosthenes implementation.
<dt><a href="Makefile">Makefile</a>
<dd>Makefile for building the example.
</dl>
</div>
</div>
<div class="changes">
<div class="h3-alike">Directories</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<dl>
<dt><a href="msvs/">msvs</a>
<dd>Contains Microsoft* Visual Studio* workspace for building and running the example (Windows* systems only).
<dt><a href="xcode/">xcode</a>
<dd>Contains Xcode* IDE workspace for building and running the example (macOS* systems only).
</dl>
<p>For information about the minimum supported version of IDE, see <a href="http://software.intel.com/en-us/articles/intel-threading-building-blocks-release-notes">release notes.</a></p>
</div>
</div>
<div class="changes">
<div class="h3-alike">Build instructions</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<p>General build directions can be found <a href="../../index.html">here</a>.</p>
</div>
</div>
<div class="changes">
<div class="h3-alike">Usage</div>
<input type="checkbox" checked="checked">
<div class="show-hide">
<dl>
<dt><tt>primes <i>-h</i></tt>
<dd>Prints the help for command line options
<dt><tt>primes [<i>n-of-threads</i>=value] [<i>number</i>=value] [<i>grain-size</i>=value] [<i>n-of-repeats</i>=value] [<i>silent</i>]</tt>
<dt><tt>primes [<i>n-of-threads</i> [<i>number</i> [<i>grain-size</i> [<i>n-of-repeats</i>]]]][<i>silent</i>]</tt>
<dd><i>n-of-threads</i> is the number of threads to use; a range of the form <i>low</i>[:<i>high</i>], where low and optional high are non-negative integers or 'auto' for a platform-specific default number.<br>
<i>number</i> is an upper bound of range to search primes in, must be a positive integer.<br>
<i>grain-size</i> is an optional grain size, must be a positive integer. <br>
<i>n-of-repeats</i> is a number of the calculation repeats, must be a positive integer.<br>
<i>silent</i> - no output except elapsed time.<br>
<dt>To run a short version of this example, e.g., for use with Intel&reg; Parallel Inspector:
<dd>Build a <i>debug</i> version of the example
(see the <a href="../../index.html">build instructions</a>).
<br>Run it with a small problem size and the desired number of threads, e.g., <tt>primes&nbsp;4&nbsp;100000</tt>.
</dl>
</div>
</div>
<br>
<a href="../index.html">Up to parent directory</a>
<hr>
<div class="changes">
<div class="h3-alike">Legal Information</div>
<input type="checkbox">
<div class="show-hide">
<p>
Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries.
<br>* Other names and brands may be claimed as the property of others.
<br>&copy; 2020, Intel Corporation
</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,268 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
A1F593A60B8F042A00073279 /* primes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* primes.cpp */; };
EA8D882D1301731B00385DE1 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA8D882C1301731B00385DE1 /* main.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
C3C5895B218B692000DAC94C /* PBXBuildRule */ = {
isa = PBXBuildRule;
compilerSpec = com.intel.compilers.icc.latest;
fileType = sourcecode.cpp;
isEditable = 1;
outputFiles = (
);
script = "# Type a script or drag a script file from your workspace to insert its path.\n";
};
/* End PBXBuildRule section */
/* Begin PBXCopyFilesBuildPhase section */
8DD76F690486A84900D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 12;
dstPath = "";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
8DD76F6C0486A84900D96B5E /* primes */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = primes; sourceTree = BUILT_PRODUCTS_DIR; };
A1F593A50B8F042A00073279 /* primes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = primes.cpp; path = ../primes.cpp; sourceTree = SOURCE_ROOT; };
EA8D882B130172E400385DE1 /* primes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = primes.h; path = ../primes.h; sourceTree = SOURCE_ROOT; };
EA8D882C1301731B00385DE1 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../main.cpp; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DD76F660486A84900D96B5E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* primes */ = {
isa = PBXGroup;
children = (
08FB7795FE84155DC02AAC07 /* Source */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
name = primes;
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
EA8D882C1301731B00385DE1 /* main.cpp */,
EA8D882B130172E400385DE1 /* primes.h */,
A1F593A50B8F042A00073279 /* primes.cpp */,
);
name = Source;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
8DD76F6C0486A84900D96B5E /* primes */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
8DD76F620486A84900D96B5E /* primes */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "primes" */;
buildPhases = (
8DD76F640486A84900D96B5E /* Sources */,
8DD76F660486A84900D96B5E /* Frameworks */,
8DD76F690486A84900D96B5E /* CopyFiles */,
);
buildRules = (
C3C5895B218B692000DAC94C /* PBXBuildRule */,
);
dependencies = (
);
name = primes;
productInstallPath = "$(HOME)/bin";
productName = primes;
productReference = 8DD76F6C0486A84900D96B5E /* primes */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1000;
};
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "primes" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* primes */;
projectDirPath = "";
projectRoot = "";
targets = (
8DD76F620486A84900D96B5E /* primes */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
8DD76F640486A84900D96B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1F593A60B8F042A00073279 /* primes.cpp in Sources */,
EA8D882D1301731B00385DE1 /* main.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
A1F593C60B8F0E6E00073279 /* Debug64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = "";
HEADER_SEARCH_PATHS = "$(inherited)";
ICC_CXX_LANG_DIALECT = "c++11";
INSTALL_PATH = "$(HOME)/bin";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = primes;
ZERO_LINK = NO;
};
name = Debug64;
};
A1F593C70B8F0E6E00073279 /* Release64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_VERSION = "";
HEADER_SEARCH_PATHS = "$(inherited)";
ICC_CXX_LANG_DIALECT = "c++11";
INSTALL_PATH = "$(HOME)/bin";
LD_RUNPATH_SEARCH_PATHS = "$(inherited)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_NAME = primes;
ZERO_LINK = NO;
};
name = Release64;
};
A1F593C80B8F0E6E00073279 /* Debug64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ENABLE_TESTABILITY = YES;
GCC_ENABLE_CPP_RTTI = YES;
GCC_MODEL_TUNING = "";
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(TBBROOT)/include",
/opt/intel/tbb/include,
);
ICC_CXX_LANG_DIALECT = "c++11";
LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
LIBRARY_SEARCH_PATHS = (
"$(TBBROOT)/lib",
/opt/intel/tbb/lib,
);
MACOSX_DEPLOYMENT_TARGET = 10.11;
ONLY_ACTIVE_ARCH = YES;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-m64",
);
OTHER_LDFLAGS = (
"-m64",
"-ltbb_debug",
);
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
SYMROOT = "/tmp/tbb-$(USER)";
VALID_ARCHS = x86_64;
};
name = Debug64;
};
A1F593C90B8F0E6E00073279 /* Release64 */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
GCC_ENABLE_CPP_RTTI = YES;
GCC_MODEL_TUNING = "";
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(TBBROOT)/include",
/opt/intel/tbb/include,
);
ICC_CXX_LANG_DIALECT = "c++11";
LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
LIBRARY_SEARCH_PATHS = (
"$(TBBROOT)/lib",
/opt/intel/tbb/lib,
);
MACOSX_DEPLOYMENT_TARGET = 10.11;
OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)",
"-m64",
);
OTHER_LDFLAGS = (
"-m64",
"-ltbb",
);
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
SYMROOT = "/tmp/tbb-$(USER)";
VALID_ARCHS = x86_64;
};
name = Release64;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "primes" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1F593C60B8F0E6E00073279 /* Debug64 */,
A1F593C70B8F0E6E00073279 /* Release64 */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release64;
};
1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "primes" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1F593C80B8F0E6E00073279 /* Debug64 */,
A1F593C90B8F0E6E00073279 /* Release64 */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release64;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}