Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
FORMUS3IC_LAS3
/
embb
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
ffa2f18a
authored
Mar 02, 2015
by
Christian Kern
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'development' into embb9_tarball_script
parents
938c3be8
ad71c970
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
48 changed files
with
471 additions
and
255 deletions
+471
-255
algorithms_cpp/include/embb/algorithms/internal/count-inl.h
+16
-13
algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h
+55
-33
algorithms_cpp/include/embb/algorithms/internal/merge_sort-inl.h
+0
-0
algorithms_cpp/include/embb/algorithms/internal/partition-inl.h
+3
-3
algorithms_cpp/include/embb/algorithms/internal/quick_sort-inl.h
+29
-9
algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h
+75
-42
algorithms_cpp/include/embb/algorithms/internal/scan-inl.h
+71
-52
algorithms_cpp/include/embb/algorithms/invoke.h
+2
-2
algorithms_cpp/include/embb/algorithms/merge_sort.h
+11
-0
algorithms_cpp/include/embb/algorithms/reduce.h
+3
-3
algorithms_cpp/include/embb/algorithms/scan.h
+3
-3
algorithms_cpp/test/count_test.cc
+2
-4
algorithms_cpp/test/for_each_test.cc
+24
-5
algorithms_cpp/test/merge_sort_test.cc
+46
-27
algorithms_cpp/test/merge_sort_test.h
+1
-1
algorithms_cpp/test/quick_sort_test.cc
+25
-6
algorithms_cpp/test/reduce_test.cc
+25
-2
algorithms_cpp/test/scan_test.cc
+28
-8
base_c/include/embb/base/c/internal/platform.h
+0
-0
base_c/test/alloc_test.h
+0
-0
base_c/test/condition_var_test.h
+0
-0
base_c/test/core_set_test.h
+0
-0
base_c/test/counter_test.h
+0
-0
base_c/test/duration_test.h
+0
-0
base_c/test/thread_index_test.h
+0
-0
base_c/test/thread_specific_storage_test.h
+0
-0
base_c/test/thread_test.h
+0
-0
base_c/test/time_test.h
+0
-0
base_cpp/include/embb/base/core_set.h
+0
-0
base_cpp/include/embb/base/duration.h
+0
-0
base_cpp/include/embb/base/exceptions.h
+0
-10
base_cpp/include/embb/base/internal/duration-inl.h
+0
-0
base_cpp/include/embb/base/internal/mutex-inl.h
+0
-0
base_cpp/include/embb/base/internal/thread-inl.h
+0
-0
base_cpp/include/embb/base/internal/thread_closures.h
+6
-6
base_cpp/include/embb/base/internal/thread_specific_storage-inl.h
+0
-0
base_cpp/include/embb/base/thread.h
+8
-8
base_cpp/include/embb/base/thread_specific_storage.h
+0
-2
base_cpp/include/embb/base/time.h
+0
-0
base_cpp/test/thread_test.h
+1
-2
dataflow_cpp/include/embb/dataflow/internal/inputs.h
+5
-5
mtapi_c/include/embb/mtapi/c/mtapi.h
+1
-1
mtapi_cpp/include/embb/mtapi/action.h
+8
-8
mtapi_cpp/include/embb/mtapi/execution_policy.h
+7
-0
mtapi_cpp/include/embb/mtapi/node.h
+10
-0
mtapi_cpp/src/execution_policy.cc
+5
-0
mtapi_cpp/src/node.cc
+1
-0
partest.tar
+0
-0
No files found.
algorithms_cpp/include/embb/algorithms/internal/count-inl.h
View file @
ffa2f18a
...
...
@@ -37,42 +37,45 @@ namespace internal {
template
<
typename
ValueType
>
class
ValueComparisonFunction
{
public
:
explicit
ValueComparisonFunction
(
const
ValueType
&
value
)
:
value_
(
value
)
{}
ValueComparisonFunction
(
const
ValueComparisonFunction
&
other
)
:
value_
(
other
.
value_
)
{}
explicit
ValueComparisonFunction
(
const
ValueType
&
value
)
:
value_
(
value
)
{}
ValueComparisonFunction
(
const
ValueComparisonFunction
&
other
)
:
value_
(
other
.
value_
)
{}
template
<
typename
ElementType
>
int
operator
()(
ElementType
element
)
{
if
(
element
==
value_
)
if
(
element
==
value_
)
{
return
1
;
else
}
else
{
return
0
;
}
}
private
:
const
ValueType
&
value_
;
ValueComparisonFunction
&
operator
=
(
const
ValueComparisonFunction
&
other
);
ValueComparisonFunction
&
operator
=
(
const
ValueComparisonFunction
&
other
);
};
template
<
typename
Function
>
class
FunctionComparisonFunction
{
public
:
explicit
FunctionComparisonFunction
(
Function
function
)
:
function_
(
function
)
{}
:
function_
(
function
)
{}
FunctionComparisonFunction
(
const
FunctionComparisonFunction
&
other
)
:
function_
(
other
.
function_
)
{}
:
function_
(
other
.
function_
)
{}
template
<
typename
ElementType
>
int
operator
()(
ElementType
element
)
{
if
(
function_
(
element
))
if
(
function_
(
element
))
{
return
1
;
else
}
else
{
return
0
;
}
}
private
:
Function
function_
;
FunctionComparisonFunction
&
operator
=
(
const
FunctionComparisonFunction
&
other
);
FunctionComparisonFunction
&
operator
=
(
const
FunctionComparisonFunction
&
other
);
};
}
// namespace internal
...
...
algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h
View file @
ffa2f18a
...
...
@@ -45,44 +45,54 @@ class ForEachFunctor {
/**
* Constructs a for-each functor with arguments.
*/
ForEachFunctor
(
RAI
first
,
RAI
last
,
Function
unary
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
)
:
first_
(
first
),
last_
(
last
),
unary_
(
unary
),
policy_
(
policy
),
block_size_
(
block_size
)
{
ForEachFunctor
(
size_t
chunk_first
,
size_t
chunk_last
,
Function
unary
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
const
BlockSizePartitioner
<
RAI
>&
partitioner
)
:
chunk_first_
(
chunk_first
),
chunk_last_
(
chunk_last
),
unary_
(
unary
),
policy_
(
policy
),
partitioner_
(
partitioner
)
{
}
void
Action
(
mtapi
::
TaskContext
&
)
{
size_t
distance
=
static_cast
<
size_t
>
(
std
::
distance
(
first_
,
last_
));
if
(
distance
==
0
)
return
;
if
(
distance
<=
block_size_
)
{
// leaf case -> do work
for
(
RAI
curIter
(
first_
);
curIter
!=
last_
;
++
curIter
)
{
unary_
(
*
curIter
);
if
(
chunk_first_
==
chunk_last_
)
{
// Leaf case, recursed to single chunk. Do work on chunk:
ChunkDescriptor
<
RAI
>
chunk
=
partitioner_
[
chunk_first_
];
RAI
first
=
chunk
.
GetFirst
();
RAI
last
=
chunk
.
GetLast
();
for
(
RAI
it
=
first
;
it
!=
last
;
++
it
)
{
unary_
(
*
it
);
}
}
else
{
// recurse further
ChunkPartitioner
<
RAI
>
partitioner
(
first_
,
last_
,
2
);
ForEachFunctor
<
RAI
,
Function
>
functorL
(
partitioner
[
0
].
GetFirst
(),
partitioner
[
0
].
GetLast
(),
unary_
,
policy_
,
block_size_
);
ForEachFunctor
<
RAI
,
Function
>
functorR
(
partitioner
[
1
].
GetFirst
(),
partitioner
[
1
].
GetLast
(),
unary_
,
policy_
,
block_size_
);
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
mtapi
::
Task
taskL
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functorL
,
&
ForEachFunctor
<
RAI
,
Function
>::
Action
),
}
else
{
// Recurse further:
size_t
chunk_split_index
=
(
chunk_first_
+
chunk_last_
)
/
2
;
// Split chunks into left / right branches:
self_t
functor_l
(
chunk_first_
,
chunk_split_index
,
unary_
,
policy_
,
partitioner_
);
self_t
functor_r
(
chunk_split_index
+
1
,
chunk_last_
,
unary_
,
policy_
,
partitioner_
);
mtapi
::
Task
task_l
=
mtapi
::
Node
::
GetInstance
().
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_l
,
&
self_t
::
Action
),
policy_
));
mtapi
::
Task
taskR
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functorR
,
&
ForEachFunctor
<
RAI
,
Function
>::
Action
),
mtapi
::
Task
task_r
=
mtapi
::
Node
::
GetInstance
().
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_r
,
&
self_t
::
Action
),
policy_
));
task
L
.
Wait
(
MTAPI_INFINITE
);
task
R
.
Wait
(
MTAPI_INFINITE
);
task
_l
.
Wait
(
MTAPI_INFINITE
);
task
_r
.
Wait
(
MTAPI_INFINITE
);
}
}
private
:
RAI
first_
;
RAI
last_
;
typedef
ForEachFunctor
<
RAI
,
Function
>
self_t
;
private
:
size_t
chunk_first_
;
size_t
chunk_last_
;
Function
unary_
;
const
embb
::
mtapi
::
ExecutionPolicy
&
policy_
;
size_t
block_size
_
;
const
BlockSizePartitioner
<
RAI
>&
partitioner
_
;
/**
* Disables assignment.
...
...
@@ -95,21 +105,33 @@ void ForEachRecursive(RAI first, RAI last, Function unary,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
)
{
typedef
typename
std
::
iterator_traits
<
RAI
>::
difference_type
difference_type
;
difference_type
distance
=
std
::
distance
(
first
,
last
);
assert
(
distance
>
0
);
if
(
distance
==
0
)
{
return
;
}
else
if
(
distance
<
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Negative range for ForEach"
);
}
unsigned
int
num_cores
=
policy
.
GetCoreCount
();
if
(
num_cores
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"No cores in execution policy"
);
}
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
// Determine actually used block size
if
(
block_size
==
0
)
{
block_size
=
(
static_cast
<
size_t
>
(
distance
)
/
n
ode
.
GetCoreCount
()
);
block_size
=
(
static_cast
<
size_t
>
(
distance
)
/
n
um_cores
);
if
(
block_size
==
0
)
{
block_size
=
1
;
}
}
//
Perform check of
task number sufficiency
//
Check
task number sufficiency
if
(((
distance
/
block_size
)
*
2
)
+
1
>
MTAPI_NODE_MAX_TASKS_DEFAULT
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Not enough MTAPI tasks available "
"
to perform the parallel foreach loop
"
);
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"
Not enough MTAPI tasks available for parallel foreach
"
);
}
ForEachFunctor
<
RAI
,
Function
>
functor
(
first
,
last
,
unary
,
policy
,
block_size
);
BlockSizePartitioner
<
RAI
>
partitioner
(
first
,
last
,
block_size
);
ForEachFunctor
<
RAI
,
Function
>
functor
(
0
,
partitioner
.
Size
()
-
1
,
unary
,
policy
,
partitioner
);
mtapi
::
Task
task
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor
,
&
ForEachFunctor
<
RAI
,
Function
>::
Action
),
...
...
@@ -127,7 +149,7 @@ void ForEachIteratorCheck(RAI first, RAI last, Function unary,
}
// namespace internal
template
<
typename
RAI
,
typename
Function
>
void
ForEach
(
RAI
first
,
RAI
last
,
Function
unary
,
void
ForEach
(
RAI
first
,
const
RAI
last
,
Function
unary
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
)
{
typename
std
::
iterator_traits
<
RAI
>::
iterator_category
category
;
internal
::
ForEachIteratorCheck
(
first
,
last
,
unary
,
policy
,
block_size
,
...
...
algorithms_cpp/include/embb/algorithms/internal/merge_sort-inl.h
View file @
ffa2f18a
This diff is collapsed.
Click to expand it.
algorithms_cpp/include/embb/algorithms/internal/partition-inl.h
View file @
ffa2f18a
...
...
@@ -71,8 +71,8 @@ const ChunkDescriptor<ForwardIterator>
ForwardIterator
last_new
=
first_new
;
if
(
index
==
elements_count
/
chunkSize
)
{
std
::
advance
(
last_new
,
elements_count
%
chunkSize
)
;
if
(
index
>=
chunks
-
1
)
{
last_new
=
last
;
}
else
{
std
::
advance
(
last_new
,
chunkSize
);
}
...
...
@@ -94,7 +94,7 @@ ChunkPartitioner<ForwardIterator>::ChunkPartitioner(ForwardIterator first,
}
else
{
// if no concrete chunk size was given, use number of cores...
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
size
=
node
.
Get
Core
Count
();
size
=
node
.
Get
WorkerThread
Count
();
}
elements_count
=
static_cast
<
size_t
>
(
std
::
distance
(
first
,
last
));
...
...
algorithms_cpp/include/embb/algorithms/internal/quick_sort-inl.h
View file @
ffa2f18a
...
...
@@ -186,16 +186,26 @@ class QuickSortFunctor {
QuickSortFunctor
(
const
QuickSortFunctor
&
);
};
}
// namespace internal
template
<
typename
RAI
,
typename
ComparisonFunction
>
void
QuickSort
(
RAI
first
,
RAI
last
,
ComparisonFunction
comparison
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
)
{
void
QuickSortIteratorCheck
(
RAI
first
,
RAI
last
,
ComparisonFunction
comparison
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
,
std
::
random_access_iterator_tag
)
{
embb
::
mtapi
::
Node
&
node
=
embb
::
mtapi
::
Node
::
GetInstance
();
typename
std
::
iterator_traits
<
RAI
>::
difference_type
distance
=
last
-
first
;
assert
(
distance
>
0
);
typedef
typename
std
::
iterator_traits
<
RAI
>::
difference_type
difference_type
;
difference_type
distance
=
std
::
distance
(
first
,
last
);
if
(
distance
==
0
)
{
return
;
}
else
if
(
distance
<
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Negative range for QuickSort"
);
}
unsigned
int
num_cores
=
policy
.
GetCoreCount
();
if
(
num_cores
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"No cores in execution policy"
);
}
if
(
block_size
==
0
)
{
block_size
=
(
static_cast
<
size_t
>
(
distance
)
/
n
ode
.
GetCoreCount
()
);
block_size
=
(
static_cast
<
size_t
>
(
distance
)
/
n
um_cores
);
if
(
block_size
==
0
)
block_size
=
1
;
}
...
...
@@ -203,13 +213,23 @@ void QuickSort(RAI first, RAI last, ComparisonFunction comparison,
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Not enough MTAPI tasks available for performing quick sort"
);
}
internal
::
QuickSortFunctor
<
RAI
,
ComparisonFunction
>
functor
(
QuickSortFunctor
<
RAI
,
ComparisonFunction
>
functor
(
first
,
last
,
comparison
,
policy
,
block_size
);
mtapi
::
Task
task
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor
,
&
internal
::
QuickSortFunctor
<
RAI
,
ComparisonFunction
>::
Action
)));
functor
,
&
QuickSortFunctor
<
RAI
,
ComparisonFunction
>::
Action
)));
task
.
Wait
(
MTAPI_INFINITE
);
}
}
// namespace internal
template
<
typename
RAI
,
typename
ComparisonFunction
>
void
QuickSort
(
RAI
first
,
RAI
last
,
ComparisonFunction
comparison
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
)
{
typedef
typename
std
::
iterator_traits
<
RAI
>::
iterator_category
category
;
internal
::
QuickSortIteratorCheck
(
first
,
last
,
comparison
,
policy
,
block_size
,
category
());
}
}
// namespace algorithms
}
// namespace embb
...
...
algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h
View file @
ffa2f18a
...
...
@@ -42,45 +42,55 @@ template<typename RAI, typename ReturnType, typename ReductionFunction,
typename
TransformationFunction
>
class
ReduceFunctor
{
public
:
ReduceFunctor
(
RAI
first
,
RAI
last
,
ReturnType
neutral
,
ReduceFunctor
(
size_t
chunk_first
,
size_t
chunk_last
,
ReturnType
neutral
,
ReductionFunction
reduction
,
TransformationFunction
transformation
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
const
BlockSizePartitioner
<
RAI
>&
partitioner
,
ReturnType
&
result
)
:
first_
(
first
),
last_
(
last
),
neutral_
(
neutral
),
reduction_
(
reduction
),
transformation_
(
transformation
),
policy_
(
policy
),
block_size_
(
block_size
),
result_
(
result
)
{
:
chunk_first_
(
chunk_first
),
chunk_last_
(
chunk_last
),
neutral_
(
neutral
),
reduction_
(
reduction
),
transformation_
(
transformation
),
policy_
(
policy
),
partitioner_
(
partitioner
),
result_
(
result
)
{
}
void
Action
(
mtapi
::
TaskContext
&
)
{
if
(
first_
==
last_
)
{
return
;
}
size_t
distance
=
static_cast
<
size_t
>
(
std
::
distance
(
first_
,
last_
)
);
if
(
distance
<=
block_size_
)
{
// leaf case -> do work
if
(
chunk_first_
==
chunk_
last_
)
{
// Leaf case, recursed to single chunk. Do work on chunk:
ChunkDescriptor
<
RAI
>
chunk
=
partitioner_
[
chunk_first_
];
RAI
first
=
chunk
.
GetFirst
(
);
RAI
last
=
chunk
.
GetLast
();
ReturnType
result
(
neutral_
);
for
(
RAI
it
er
=
first_
;
iter
!=
last_
;
++
iter
)
{
result
=
reduction_
(
result
,
transformation_
(
*
it
er
));
for
(
RAI
it
=
first
;
it
!=
last
;
++
it
)
{
result
=
reduction_
(
result
,
transformation_
(
*
it
));
}
result_
=
result
;
}
else
{
// recurse further
internal
::
ChunkPartitioner
<
RAI
>
partitioner
(
first_
,
last_
,
2
);
}
else
{
// Recurse further:
size_t
chunk_split_index
=
(
chunk_first_
+
chunk_last_
)
/
2
;
// Split chunks into left / right branches:
ReturnType
result_l
(
neutral_
);
ReturnType
result_r
(
neutral_
);
ReduceFunctor
functor_l
(
partitioner
[
0
].
GetFirst
()
,
partitioner
[
0
].
GetLast
()
,
self_t
functor_l
(
chunk_first_
,
chunk_split_index
,
neutral_
,
reduction_
,
transformation_
,
policy_
,
block_size_
,
result_l
);
ReduceFunctor
functor_r
(
partitioner
[
1
].
GetFirst
(),
partitioner
[
1
].
GetLast
(),
partitioner_
,
result_l
);
self_t
functor_r
(
chunk_split_index
+
1
,
chunk_last_
,
neutral_
,
reduction_
,
transformation_
,
policy_
,
block_size_
,
result_r
);
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
mtapi
::
Task
task_l
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_l
,
&
ReduceFunctor
::
Action
),
policy_
));
mtapi
::
Task
task_r
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_r
,
&
ReduceFunctor
::
Action
),
policy_
));
partitioner_
,
result_r
);
mtapi
::
Task
task_l
=
mtapi
::
Node
::
GetInstance
().
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_l
,
&
self_t
::
Action
),
policy_
));
mtapi
::
Task
task_r
=
mtapi
::
Node
::
GetInstance
().
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_r
,
&
self_t
::
Action
),
policy_
));
task_l
.
Wait
(
MTAPI_INFINITE
);
task_r
.
Wait
(
MTAPI_INFINITE
);
result_
=
reduction_
(
result_l
,
result_r
);
...
...
@@ -88,15 +98,23 @@ class ReduceFunctor {
}
private
:
RAI
first_
;
RAI
last_
;
typedef
ReduceFunctor
<
RAI
,
ReturnType
,
ReductionFunction
,
TransformationFunction
>
self_t
;
private
:
size_t
chunk_first_
;
size_t
chunk_last_
;
ReturnType
neutral_
;
ReductionFunction
reduction_
;
TransformationFunction
transformation_
;
const
embb
::
mtapi
::
ExecutionPolicy
&
policy_
;
size_t
block_size
_
;
const
BlockSizePartitioner
<
RAI
>&
partitioner
_
;
ReturnType
&
result_
;
/**
* Disables assignment and copy-construction.
*/
ReduceFunctor
&
operator
=
(
const
ReduceFunctor
&
);
ReduceFunctor
(
const
ReduceFunctor
&
);
};
...
...
@@ -110,27 +128,42 @@ ReturnType ReduceRecursive(RAI first, RAI last, ReturnType neutral,
size_t
block_size
)
{
typedef
typename
std
::
iterator_traits
<
RAI
>::
difference_type
difference_type
;
difference_type
distance
=
std
::
distance
(
first
,
last
);
assert
(
distance
>
0
);
if
(
distance
==
0
)
{
return
neutral
;
}
else
if
(
distance
<
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Negative range for Reduce"
);
}
unsigned
int
num_cores
=
policy
.
GetCoreCount
();
if
(
num_cores
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"No cores in execution policy"
);
}
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
size_t
used_block_size
=
block_size
;
if
(
used_block_size
==
0
)
{
used_block_size
=
static_cast
<
size_t
>
(
distance
)
/
node
.
GetCoreCount
();
if
(
used_block_size
==
0
)
used_block_size
=
1
;
// Determine actually used block size
if
(
block_size
==
0
)
{
block_size
=
(
static_cast
<
size_t
>
(
distance
)
/
num_cores
);
if
(
block_size
==
0
)
{
block_size
=
1
;
}
if
(((
distance
/
used_block_size
)
*
2
)
+
1
>
MTAPI_NODE_MAX_TASKS_DEFAULT
)
{
}
// Perform check of task number sufficiency
if
(((
distance
/
block_size
)
*
2
)
+
1
>
MTAPI_NODE_MAX_TASKS_DEFAULT
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Number of computation tasks required in reduction would "
"exceed MTAPI maximum number of tasks"
);
}
ReturnType
result
=
neutral
;
typedef
ReduceFunctor
<
RAI
,
ReturnType
,
ReductionFunction
,
TransformationFunction
>
Functor
;
Functor
functor
(
first
,
last
,
neutral
,
reduction
,
transformation
,
policy
,
used_block_size
,
result
);
mtapi
::
Task
task
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
BlockSizePartitioner
<
RAI
>
partitioner
(
first
,
last
,
block_size
);
ReturnType
result
=
neutral
;
Functor
functor
(
0
,
partitioner
.
Size
()
-
1
,
neutral
,
reduction
,
transformation
,
policy
,
partitioner
,
result
);
mtapi
::
Task
task
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor
,
&
Functor
::
Action
),
policy
));
task
.
Wait
(
MTAPI_INFINITE
);
return
result
;
...
...
algorithms_cpp/include/embb/algorithms/internal/scan-inl.h
View file @
ffa2f18a
...
...
@@ -41,73 +41,79 @@ template<typename RAIIn, typename RAIOut, typename ReturnType,
typename
ScanFunction
,
typename
TransformationFunction
>
class
ScanFunctor
{
public
:
ScanFunctor
(
RAIIn
first
,
RAIIn
last
,
RAIOut
output_iterator
,
ScanFunctor
(
size_t
chunk_first
,
size_t
chunk_
last
,
RAIOut
output_iterator
,
ReturnType
neutral
,
ScanFunction
scan
,
TransformationFunction
transformation
,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
,
size_t
block_size
,
ReturnType
*
tree_values
,
size_t
node_id
,
const
BlockSizePartitioner
<
RAIIn
>&
partitioner
,
ReturnType
*
tree_values
,
size_t
node_id
,
bool
going_down
)
:
policy_
(
policy
),
first_
(
first
),
last_
(
last
),
:
policy_
(
policy
),
chunk_first_
(
chunk_first
),
chunk_last_
(
chunk_
last
),
output_iterator_
(
output_iterator
),
scan_
(
scan
),
transformation_
(
transformation
),
neutral_
(
neutral
),
block_size_
(
block_size
),
tree_values_
(
tree_values
),
neutral_
(
neutral
),
partitioner_
(
partitioner
),
tree_values_
(
tree_values
),
node_id_
(
node_id
),
parent_value_
(
neutral
),
is_first_pass_
(
going_down
)
{
}
void
Action
(
mtapi
::
TaskContext
&
)
{
if
(
first_
==
last_
)
{
return
;
}
size_t
distance
=
static_cast
<
size_t
>
(
std
::
distance
(
first_
,
last_
));
if
(
distance
<=
block_size_
)
{
// leaf case -> do work
if
(
is_first_pass_
)
{
RAIIn
iter_in
=
first_
;
if
(
chunk_first_
==
chunk_last_
)
{
ChunkDescriptor
<
RAIIn
>
chunk
=
partitioner_
[
chunk_first_
];
RAIIn
iter_in
=
chunk
.
GetFirst
();
RAIIn
last_in
=
chunk
.
GetLast
();
RAIOut
iter_out
=
output_iterator_
;
ReturnType
result
=
transformation_
(
*
first_
);
// leaf case -> do work
if
(
is_first_pass_
)
{
ReturnType
result
=
transformation_
(
*
iter_in
);
*
iter_out
=
result
;
++
iter_in
;
++
iter_out
;
while
(
iter_in
!=
last_
)
{
for
(;
iter_in
!=
last_in
;
++
iter_in
,
++
iter_out
)
{
result
=
scan_
(
result
,
transformation_
(
*
iter_in
));
*
iter_out
=
result
;
++
iter_in
;
++
iter_out
;
}
SetTreeValue
(
result
);
}
else
{
// Second pass
RAIIn
iter_in
=
first_
;
RAIOut
iter_out
=
output_iterator_
;
while
(
iter_in
!=
last_
)
{
}
else
{
// Second pass
for
(;
iter_in
!=
last_in
;
++
iter_in
,
++
iter_out
)
{
*
iter_out
=
scan_
(
parent_value_
,
*
iter_out
);
++
iter_in
;
++
iter_out
;
}
}
}
else
{
internal
::
ChunkPartitioner
<
RAIIn
>
partitioner
(
first_
,
last_
,
2
);
ScanFunctor
functor_l
(
partitioner
[
0
].
GetFirst
(),
partitioner
[
0
].
GetLast
(),
// recurse further
size_t
chunk_split_index
=
(
chunk_first_
+
chunk_last_
)
/
2
;
// Split chunks into left / right branches:
ScanFunctor
functor_l
(
chunk_first_
,
chunk_split_index
,
output_iterator_
,
neutral_
,
scan_
,
transformation_
,
policy_
,
block_size
_
,
tree_values_
,
node_id_
,
policy_
,
partitioner
_
,
tree_values_
,
node_id_
,
is_first_pass_
);
ScanFunctor
functor_r
(
partitioner
[
1
].
GetFirst
(),
partitioner
[
1
].
GetLast
(),
ScanFunctor
functor_r
(
chunk_split_index
+
1
,
chunk_last_
,
output_iterator_
,
neutral_
,
scan_
,
transformation_
,
policy_
,
block_size
_
,
tree_values_
,
node_id_
,
policy_
,
partitioner
_
,
tree_values_
,
node_id_
,
is_first_pass_
);
functor_l
.
SetID
(
1
);
functor_r
.
SetID
(
2
);
functor_l
.
SetID
(
LEFT
);
functor_r
.
SetID
(
RIGHT
);
// Advance output iterator of right branch:
ChunkDescriptor
<
RAIIn
>
chunk_left
=
partitioner_
[
chunk_first_
];
ChunkDescriptor
<
RAIIn
>
chunk_right
=
partitioner_
[
chunk_split_index
+
1
];
std
::
advance
(
functor_r
.
output_iterator_
,
std
::
distance
(
functor_l
.
first_
,
functor_r
.
first_
));
std
::
distance
(
chunk_left
.
GetFirst
(),
chunk_right
.
GetFirst
()
));
if
(
!
is_first_pass_
)
{
functor_l
.
parent_value_
=
parent_value_
;
functor_r
.
parent_value_
=
functor_l
.
GetTreeValue
()
+
parent_value_
;
}
// Spawn tasks to recurse:
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
mtapi
::
Task
task_l
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_l
,
&
ScanFunctor
::
Action
),
mtapi
::
Task
task_l
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_l
,
&
ScanFunctor
::
Action
),
policy_
));
mtapi
::
Task
task_r
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_r
,
&
ScanFunctor
::
Action
),
mtapi
::
Task
task_r
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_r
,
&
ScanFunctor
::
Action
),
policy_
));
// Wait for tasks to complete:
task_l
.
Wait
(
MTAPI_INFINITE
);
task_r
.
Wait
(
MTAPI_INFINITE
);
SetTreeValue
(
scan_
(
functor_l
.
GetTreeValue
(),
functor_r
.
GetTreeValue
()));
...
...
@@ -123,23 +129,25 @@ class ScanFunctor {
}
private
:
static
const
int
LEFT
=
1
;
static
const
int
RIGHT
=
2
;
const
embb
::
mtapi
::
ExecutionPolicy
&
policy_
;
RAIIn
first_
;
RAIIn
last_
;
size_t
chunk_
first_
;
size_t
chunk_
last_
;
RAIOut
output_iterator_
;
ScanFunction
scan_
;
TransformationFunction
transformation_
;
ReturnType
neutral_
;
size_t
block_size
_
;
const
BlockSizePartitioner
<
RAIIn
>&
partitioner
_
;
ReturnType
*
tree_values_
;
size_t
node_id_
;
ReturnType
parent_value_
;
bool
is_first_pass_
;
void
SetID
(
int
is_left
)
{
if
(
is_left
==
1
)
{
void
SetID
(
int
branch
)
{
if
(
branch
==
LEFT
)
{
node_id_
=
2
*
node_id_
+
1
;
}
else
if
(
is_left
==
2
)
{
}
else
if
(
branch
==
RIGHT
)
{
node_id_
=
2
*
node_id_
+
2
;
}
}
...
...
@@ -165,37 +173,48 @@ void ScanIteratorCheck(RAIIn first, RAIIn last, RAIOut output_iterator,
std
::
random_access_iterator_tag
)
{
typedef
typename
std
::
iterator_traits
<
RAIIn
>::
difference_type
difference_type
;
difference_type
distance
=
std
::
distance
(
first
,
last
);
if
(
distance
<
=
0
)
{
if
(
distance
=
=
0
)
{
return
;
}
else
if
(
distance
<
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Negative range for Scan"
);
}
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
unsigned
int
num_cores
=
policy
.
GetCoreCount
();
if
(
num_cores
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"No cores in execution policy"
);
}
ReturnType
values
[
MTAPI_NODE_MAX_TASKS_DEFAULT
];
size_t
used_block_size
=
block_size
;
if
(
block_size
==
0
)
{
used_block_size
=
static_cast
<
size_t
>
(
distance
)
/
node
.
GetCoreCount
();
if
(
used_block_size
==
0
)
used_block_size
=
1
;
block_size
=
static_cast
<
size_t
>
(
distance
)
/
num_cores
;
if
(
block_size
==
0
)
{
block_size
=
1
;
}
}
if
(((
distance
/
used_
block_size
)
*
2
)
+
1
>
MTAPI_NODE_MAX_TASKS_DEFAULT
)
{
if
(((
distance
/
block_size
)
*
2
)
+
1
>
MTAPI_NODE_MAX_TASKS_DEFAULT
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Number of computation tasks required in scan "
"exceeds MTAPI maximum number of tasks"
);
"Not enough MTAPI tasks available for parallel scan"
);
}
// first pass. Calculates prefix sums for leaves and when recursion returns
// it creates the tree.
typedef
ScanFunctor
<
RAIIn
,
RAIOut
,
ReturnType
,
ScanFunction
,
TransformationFunction
>
Functor
;
Functor
functor_down
(
first
,
last
,
output_iterator
,
neutral
,
scan
,
transformation
,
policy
,
used_block_size
,
values
,
0
,
true
);
mtapi
::
Node
&
node
=
mtapi
::
Node
::
GetInstance
();
BlockSizePartitioner
<
RAIIn
>
partitioner_down
(
first
,
last
,
block_size
);
Functor
functor_down
(
0
,
partitioner_down
.
Size
()
-
1
,
output_iterator
,
neutral
,
scan
,
transformation
,
policy
,
partitioner_down
,
values
,
0
,
true
);
mtapi
::
Task
task_down
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_down
,
&
Functor
::
Action
),
policy
));
task_down
.
Wait
(
MTAPI_INFINITE
);
// Second pass. Gives to each leaf the part of the prefix missing
Functor
functor_up
(
first
,
last
,
output_iterator
,
neutral
,
scan
,
transformation
,
policy
,
used_block_size
,
values
,
0
,
false
);
BlockSizePartitioner
<
RAIIn
>
partitioner_up
(
first
,
last
,
block_size
);
Functor
functor_up
(
0
,
partitioner_up
.
Size
()
-
1
,
output_iterator
,
neutral
,
scan
,
transformation
,
policy
,
partitioner_up
,
values
,
0
,
false
);
mtapi
::
Task
task_up
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor_up
,
&
Functor
::
Action
),
policy
));
...
...
algorithms_cpp/include/embb/algorithms/invoke.h
View file @
ffa2f18a
...
...
@@ -58,7 +58,7 @@ typedef embb::base::Function<void> InvokeFunctionType;
template
<
typename
Function1
,
...
>
void
Invoke
(
Function1
func1
,
/**< [in] First function to invoke */
/**< [in] First function
object
to invoke */
...);
/**
...
...
@@ -72,7 +72,7 @@ void Invoke(
template
<
typename
Function1
,
...
>
void
Invoke
(
Function1
func1
,
/**< [in] Function to invoke */
/**< [in] Function
object
to invoke */
...,
const
embb
::
mtapi
::
ExecutionPolicy
&
policy
/**< [in] embb::mtapi::ExecutionPolicy to use */
...
...
algorithms_cpp/include/embb/algorithms/merge_sort.h
View file @
ffa2f18a
...
...
@@ -167,9 +167,20 @@ void MergeSortAllocate(
typedef
base
::
Allocation
Alloc
;
typename
std
::
iterator_traits
<
RAI
>::
difference_type
distance
=
last
-
first
;
typedef
typename
std
::
iterator_traits
<
RAI
>::
value_type
value_type
;
if
(
distance
==
0
)
{
return
;
}
else
if
(
distance
<
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Negative range for MergeSort"
);
}
value_type
*
temporary
=
static_cast
<
value_type
*>
(
Alloc
::
Allocate
(
distance
*
sizeof
(
value_type
)));
EMBB_TRY
{
MergeSort
(
first
,
last
,
temporary
,
comparison
,
policy
,
block_size
);
}
EMBB_CATCH
(
embb
::
base
::
ErrorException
&
e
)
{
// embb exception handling does not support catch(...) and rethrow yet.
Alloc
::
Free
(
temporary
);
EMBB_THROW
(
embb
::
base
::
ErrorException
,
e
.
what
());
}
Alloc
::
Free
(
temporary
);
}
...
...
algorithms_cpp/include/embb/algorithms/reduce.h
View file @
ffa2f18a
...
...
@@ -68,10 +68,10 @@ namespace algorithms {
* \tparam RAI Random access iterator
* \tparam ReturnType Type of result of reduction operation, deduced from
* \c neutral
* \tparam ReductionFunction Binary reduction function with signature
* \tparam ReductionFunction Binary reduction function
object
with signature
* <tt>ReturnType ReductionFunction(ReturnType, ReturnType)</tt>.
* \tparam TransformationFunction Unary transformation function
with signature
* <tt>ReturnType TransformationFunction(typename
* \tparam TransformationFunction Unary transformation function
object with
*
signature
<tt>ReturnType TransformationFunction(typename
* std::iterator_traits<RAI>::value_type)</tt>
*/
template
<
typename
RAI
,
typename
ReturnType
,
typename
ReductionFunction
,
...
...
algorithms_cpp/include/embb/algorithms/scan.h
View file @
ffa2f18a
...
...
@@ -71,10 +71,10 @@ namespace algorithms {
* \tparam RAIOut Random access iterator type of output range
* \tparam ReturnType Type of output elements of scan operation, deduced from
* \c neutral
* \tparam ScanFunction Binary scan function with signature
* \tparam ScanFunction Binary scan function
object
with signature
* <tt>ReturnType ScanFunction(ReturnType, ReturnType)</tt>
* \tparam TransformationFunction Unary transformation function
with signature
* <tt>ReturnType TransformationFunction(typename
* \tparam TransformationFunction Unary transformation function
object with
*
signature
<tt>ReturnType TransformationFunction(typename
* std::iterator_traits<RAIIn>::value_type)</tt>.
*/
template
<
typename
RAIIn
,
typename
RAIOut
,
typename
ReturnType
,
...
...
algorithms_cpp/test/count_test.cc
View file @
ffa2f18a
...
...
@@ -60,7 +60,7 @@ CountTest::CountTest() {
void
CountTest
::
TestDataStructures
()
{
using
embb
::
algorithms
::
Count
;
const
int
size
=
10
;
int
array
[]
=
{
10
,
20
,
30
,
30
,
20
,
10
,
10
,
20
,
20
,
20
};
int
array
[]
=
{
10
,
20
,
30
,
30
,
20
,
10
,
10
,
20
,
20
,
20
};
std
::
vector
<
int
>
vector
(
array
,
array
+
size
);
std
::
deque
<
int
>
deque
(
array
,
array
+
size
);
const
std
::
vector
<
int
>
const_vector
(
array
,
array
+
size
);
...
...
@@ -74,7 +74,7 @@ void CountTest::TestDataStructures() {
void
CountTest
::
TestCountIf
()
{
using
embb
::
algorithms
::
CountIf
;
const
int
size
=
10
;
int
array
[]
=
{
10
,
21
,
30
,
31
,
20
,
11
,
10
,
21
,
20
,
20
};
int
array
[]
=
{
10
,
21
,
30
,
31
,
20
,
11
,
10
,
21
,
20
,
20
};
PT_EXPECT_EQ
(
CountIf
(
array
,
array
+
size
,
IsEven
()),
6
);
PT_EXPECT_EQ
(
CountIf
(
array
,
array
+
size
,
&
IsEvenFunction
),
6
);
}
...
...
@@ -128,8 +128,6 @@ void CountTest::TestPolicy() {
PT_EXPECT_EQ
(
Count
(
vector
.
begin
(),
vector
.
end
(),
10
,
ExecutionPolicy
()),
3
);
PT_EXPECT_EQ
(
Count
(
vector
.
begin
(),
vector
.
end
(),
10
,
ExecutionPolicy
(
true
)),
3
);
PT_EXPECT_EQ
(
Count
(
vector
.
begin
(),
vector
.
end
(),
10
,
ExecutionPolicy
(
false
)),
3
);
PT_EXPECT_EQ
(
Count
(
vector
.
begin
(),
vector
.
end
(),
10
,
ExecutionPolicy
(
true
,
1
)),
3
);
}
...
...
algorithms_cpp/test/for_each_test.cc
View file @
ffa2f18a
...
...
@@ -207,16 +207,35 @@ void ForEachTest::TestPolicy() {
}
vector
=
init
;
ForEach
(
vector
.
begin
(),
vector
.
end
(),
Square
(),
ExecutionPolicy
(
false
));
ForEach
(
vector
.
begin
(),
vector
.
end
(),
Square
(),
ExecutionPolicy
(
true
,
1
));
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
PT_EXPECT_EQ
(
vector
[
i
],
init
[
i
]
*
init
[
i
]);
}
vector
=
init
;
ForEach
(
vector
.
begin
(),
vector
.
end
(),
Square
(),
ExecutionPolicy
(
true
,
1
));
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
PT_EXPECT_EQ
(
vector
[
i
],
init
[
i
]
*
init
[
i
]);
// ForEach on empty list should not throw:
ForEach
(
vector
.
begin
(),
vector
.
begin
(),
Square
());
#ifdef EMBB_USE_EXCEPTIONS
bool
empty_core_set_thrown
=
false
;
try
{
ForEach
(
vector
.
begin
(),
vector
.
end
(),
Square
(),
ExecutionPolicy
(
false
));
}
catch
(
embb
::
base
::
ErrorException
&
)
{
empty_core_set_thrown
=
true
;
}
PT_EXPECT_MSG
(
empty_core_set_thrown
,
"Empty core set should throw ErrorException"
);
bool
negative_range_thrown
=
false
;
try
{
std
::
vector
<
int
>::
iterator
second
=
vector
.
begin
()
+
1
;
ForEach
(
second
,
vector
.
begin
(),
Square
());
}
catch
(
embb
::
base
::
ErrorException
&
)
{
negative_range_thrown
=
true
;
}
PT_EXPECT_MSG
(
negative_range_thrown
,
"Negative range should throw ErrorException"
);
#endif
}
void
ForEachTest
::
StressTest
()
{
...
...
algorithms_cpp/test/merge_sort_test.cc
View file @
ffa2f18a
...
...
@@ -156,28 +156,28 @@ void MergeSortTest::TestRanges() {
}
}
//
void MergeSortTest::TestBlockSizes() {
//
using embb::algorithms::MergeSortAllocate;
// using embb::algorithms
::ExecutionPolicy;
//
size_t count = 4;
//
std::vector<int> init(count);
//
std::vector<int> vector(count);
//
std::vector<int> vector_copy(count);
//
for (size_t i = count - 1; i > 0; i--) {
//
init[i] = static_cast<int>(i+2);
//
}
//
vector_copy = init;
//
std::sort(vector_copy.begin(), vector_copy.end());
//
//
for (size_t block_size = 1; block_size < count + 2; block_size++) {
//
vector = init;
//
MergeSortAllocate(vector.begin(), vector.end(), std::less<int>(),
//
ExecutionPolicy(), block_size);
//
for (size_t i = 0; i < count; i++) {
//
PT_EXPECT_EQ(vector[i], vector_copy[i]);
//
}
//
}
//
}
void
MergeSortTest
::
TestBlockSizes
()
{
using
embb
::
algorithms
::
MergeSortAllocate
;
using
embb
::
mtapi
::
ExecutionPolicy
;
size_t
count
=
4
;
std
::
vector
<
int
>
init
(
count
);
std
::
vector
<
int
>
vector
(
count
);
std
::
vector
<
int
>
vector_copy
(
count
);
for
(
size_t
i
=
count
-
1
;
i
>
0
;
i
--
)
{
init
[
i
]
=
static_cast
<
int
>
(
i
+
2
);
}
vector_copy
=
init
;
std
::
sort
(
vector_copy
.
begin
(),
vector_copy
.
end
());
for
(
size_t
block_size
=
1
;
block_size
<
count
+
2
;
block_size
++
)
{
vector
=
init
;
MergeSortAllocate
(
vector
.
begin
(),
vector
.
end
(),
std
::
less
<
int
>
(),
ExecutionPolicy
(),
block_size
);
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
PT_EXPECT_EQ
(
vector
[
i
],
vector_copy
[
i
]);
}
}
}
void
MergeSortTest
::
TestPolicy
()
{
using
embb
::
algorithms
::
MergeSortAllocate
;
...
...
@@ -208,17 +208,36 @@ void MergeSortTest::TestPolicy() {
vector
=
init
;
MergeSortAllocate
(
vector
.
begin
(),
vector
.
end
(),
std
::
less
<
int
>
(),
ExecutionPolicy
(
false
));
ExecutionPolicy
(
true
,
1
));
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
PT_EXPECT_EQ
(
vector_copy
[
i
],
vector
[
i
]);
}
vector
=
init
;
// MergeSort on empty list should not throw:
MergeSortAllocate
(
vector
.
begin
(),
vector
.
begin
(),
std
::
less
<
int
>
());
#ifdef EMBB_USE_EXCEPTIONS
bool
empty_core_set_thrown
=
false
;
try
{
MergeSortAllocate
(
vector
.
begin
(),
vector
.
end
(),
std
::
less
<
int
>
(),
ExecutionPolicy
(
true
,
1
));
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
PT_EXPECT_EQ
(
vector_copy
[
i
],
vector
[
i
]);
ExecutionPolicy
(
false
));
}
catch
(
embb
::
base
::
ErrorException
&
)
{
empty_core_set_thrown
=
true
;
}
PT_EXPECT_MSG
(
empty_core_set_thrown
,
"Empty core set should throw ErrorException"
);
bool
negative_range_thrown
=
false
;
try
{
std
::
vector
<
int
>::
iterator
second
=
vector
.
begin
()
+
1
;
MergeSortAllocate
(
second
,
vector
.
begin
(),
std
::
less
<
int
>
());
}
catch
(
embb
::
base
::
ErrorException
&
)
{
negative_range_thrown
=
true
;
}
PT_EXPECT_MSG
(
negative_range_thrown
,
"Negative range should throw ErrorException"
);
#endif
}
void
MergeSortTest
::
StressTest
()
{
...
...
algorithms_cpp/test/merge_sort_test.h
View file @
ffa2f18a
...
...
@@ -58,7 +58,7 @@ class MergeSortTest : public partest::TestCase {
/**
* Tests various block sizes for the workers.
*/
//
void TestBlockSizes();
void
TestBlockSizes
();
/**
* Tests setting policies (without checking their actual execution).
...
...
algorithms_cpp/test/quick_sort_test.cc
View file @
ffa2f18a
...
...
@@ -214,17 +214,36 @@ void QuickSortTest::TestPolicy() {
vector
=
init
;
QuickSort
(
vector
.
begin
(),
vector
.
end
(),
std
::
greater
<
int
>
(),
ExecutionPolicy
(
false
));
ExecutionPolicy
(
true
,
1
));
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
PT_EXPECT_EQ
(
vector_copy
[
i
],
vector
[
i
]);
}
vector
=
init
;
QuickSort
(
vector
.
begin
(),
vector
.
end
(),
std
::
greater
<
int
>
(),
ExecutionPolicy
(
true
,
1
));
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
PT_EXPECT_EQ
(
vector_copy
[
i
],
vector
[
i
]);
// MergeSort on empty list should not throw:
QuickSort
(
vector
.
begin
(),
vector
.
begin
(),
std
::
less
<
int
>
());
#ifdef EMBB_USE_EXCEPTIONS
bool
empty_core_set_thrown
=
false
;
try
{
QuickSort
(
vector
.
begin
(),
vector
.
end
(),
std
::
less
<
int
>
(),
ExecutionPolicy
(
false
));
}
catch
(
embb
::
base
::
ErrorException
&
)
{
empty_core_set_thrown
=
true
;
}
PT_EXPECT_MSG
(
empty_core_set_thrown
,
"Empty core set should throw ErrorException"
);
bool
negative_range_thrown
=
false
;
try
{
std
::
vector
<
int
>::
iterator
second
=
vector
.
begin
()
+
1
;
QuickSort
(
second
,
vector
.
begin
(),
std
::
less
<
int
>
());
}
catch
(
embb
::
base
::
ErrorException
&
)
{
negative_range_thrown
=
true
;
}
PT_EXPECT_MSG
(
negative_range_thrown
,
"Negative range should throw ErrorException"
);
#endif
}
void
QuickSortTest
::
StressTest
()
{
...
...
algorithms_cpp/test/reduce_test.cc
View file @
ffa2f18a
...
...
@@ -179,10 +179,33 @@ void ReduceTest::TestPolicy() {
Identity
(),
ExecutionPolicy
()),
sum
);
PT_EXPECT_EQ
(
Reduce
(
vector
.
begin
(),
vector
.
end
(),
0
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
true
)),
sum
);
PT_EXPECT_EQ
(
Reduce
(
vector
.
begin
(),
vector
.
end
(),
0
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
false
)),
sum
);
PT_EXPECT_EQ
(
Reduce
(
vector
.
begin
(),
vector
.
end
(),
0
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
true
,
1
)),
sum
);
// Empty list should return neutral element:
PT_EXPECT_EQ
(
Reduce
(
vector
.
begin
(),
vector
.
begin
(),
41
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
true
,
1
)),
41
);
#ifdef EMBB_USE_EXCEPTIONS
bool
empty_core_set_thrown
=
false
;
try
{
Reduce
(
vector
.
begin
(),
vector
.
end
(),
0
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
false
));
}
catch
(
embb
::
base
::
ErrorException
&
)
{
empty_core_set_thrown
=
true
;
}
PT_EXPECT_MSG
(
empty_core_set_thrown
,
"Empty core set should throw ErrorException"
);
bool
negative_range_thrown
=
false
;
try
{
std
::
vector
<
int
>::
iterator
second
=
vector
.
begin
()
+
1
;
Reduce
(
second
,
vector
.
begin
(),
0
,
std
::
plus
<
int
>
());
}
catch
(
embb
::
base
::
ErrorException
&
)
{
negative_range_thrown
=
true
;
}
PT_EXPECT_MSG
(
negative_range_thrown
,
"Negative range should throw ErrorException"
);
#endif
}
void
ReduceTest
::
StressTest
()
{
...
...
algorithms_cpp/test/scan_test.cc
View file @
ffa2f18a
...
...
@@ -284,21 +284,41 @@ void ScanTest::TestPolicy() {
outputVector
=
init
;
Scan
(
vector
.
begin
(),
vector
.
end
(),
outputVector
.
begin
(),
0
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
false
));
Identity
(),
ExecutionPolicy
(
true
,
1
));
expected
=
0
;
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
expected
+=
vector
[
i
];
PT_EXPECT_EQ
(
expected
,
outputVector
[
i
]);
}
// Empty list should not throw and not change output:
outputVector
=
init
;
Scan
(
vector
.
begin
(),
vector
.
end
(),
outputVector
.
begin
(),
0
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
true
,
1
));
expected
=
0
;
for
(
size_t
i
=
0
;
i
<
count
;
i
++
)
{
expected
+=
vector
[
i
];
PT_EXPECT_EQ
(
expected
,
outputVector
[
i
]);
std
::
vector
<
int
>::
iterator
out_it
=
outputVector
.
begin
();
Scan
(
vector
.
begin
(),
vector
.
begin
(),
out_it
,
0
,
std
::
plus
<
int
>
());
PT_EXPECT
(
out_it
==
outputVector
.
begin
());
#ifdef EMBB_USE_EXCEPTIONS
bool
empty_core_set_thrown
=
false
;
try
{
Scan
(
vector
.
begin
(),
vector
.
end
(),
outputVector
.
begin
(),
0
,
std
::
plus
<
int
>
(),
Identity
(),
ExecutionPolicy
(
false
));
}
catch
(
embb
::
base
::
ErrorException
&
)
{
empty_core_set_thrown
=
true
;
}
PT_EXPECT_MSG
(
empty_core_set_thrown
,
"Empty core set should throw ErrorException"
);
bool
negative_range_thrown
=
false
;
try
{
std
::
vector
<
int
>::
iterator
second
=
vector
.
begin
()
+
1
;
Scan
(
second
,
vector
.
begin
(),
outputVector
.
begin
(),
0
,
std
::
plus
<
int
>
());
}
catch
(
embb
::
base
::
ErrorException
&
)
{
negative_range_thrown
=
true
;
}
PT_EXPECT_MSG
(
negative_range_thrown
,
"Negative range should throw ErrorException"
);
#endif
}
void
ScanTest
::
StressTest
()
{
...
...
base_c/include/embb/base/c/internal/platform.h
View file @
ffa2f18a
base_c/test/alloc_test.h
View file @
ffa2f18a
base_c/test/condition_var_test.h
View file @
ffa2f18a
base_c/test/core_set_test.h
View file @
ffa2f18a
base_c/test/counter_test.h
View file @
ffa2f18a
base_c/test/duration_test.h
View file @
ffa2f18a
base_c/test/thread_index_test.h
View file @
ffa2f18a
base_c/test/thread_specific_storage_test.h
View file @
ffa2f18a
base_c/test/thread_test.h
View file @
ffa2f18a
base_c/test/time_test.h
View file @
ffa2f18a
base_cpp/include/embb/base/core_set.h
View file @
ffa2f18a
base_cpp/include/embb/base/duration.h
View file @
ffa2f18a
base_cpp/include/embb/base/exceptions.h
View file @
ffa2f18a
...
...
@@ -175,16 +175,6 @@ class Exception : public std::exception {
}
/**
* Returns the error message.
* This is here for compatibility with std::exception.
*
* \return Pointer to error message
*/
virtual
const
char
*
what
()
const
throw
()
{
return
What
();
}
/**
* Returns an integer code representing the exception.
*
* \return %Exception code
...
...
base_cpp/include/embb/base/internal/duration-inl.h
View file @
ffa2f18a
base_cpp/include/embb/base/internal/mutex-inl.h
View file @
ffa2f18a
base_cpp/include/embb/base/internal/thread-inl.h
View file @
ffa2f18a
base_cpp/include/embb/base/internal/thread_closures.h
View file @
ffa2f18a
...
...
@@ -36,8 +36,8 @@ namespace internal {
/**
* Thread closure for thread start function with no arguments.
*
* Provides a thread start function
calling a callable entity such as a function
*
pointer or functor
.
* Provides a thread start function
from which a priorly stored function object
*
is called
.
*/
template
<
typename
Function
>
struct
ThreadClosure
{
...
...
@@ -56,8 +56,8 @@ struct ThreadClosure {
/**
* Thread closure for thread start function with one argument.
*
* Provides a thread start function
calling a callable entity such as a function
*
pointer or functor
.
* Provides a thread start function
from which a priorly stored function object
*
is called
.
*/
template
<
typename
Function
,
typename
Arg1
>
struct
ThreadClosureArg1
{
...
...
@@ -78,8 +78,8 @@ struct ThreadClosureArg1 {
/**
* Thread closure for thread start function with two arguments.
*
* Provides a thread start function
calling a callable entity such as a function
*
pointer or functor
.
* Provides a thread start function
from which a priorly stored function object
*
is called
.
*/
template
<
typename
Function
,
typename
Arg1
,
typename
Arg2
>
struct
ThreadClosureArg2
{
...
...
base_cpp/include/embb/base/internal/thread_specific_storage-inl.h
View file @
ffa2f18a
base_cpp/include/embb/base/thread.h
View file @
ffa2f18a
...
...
@@ -154,12 +154,12 @@ class Thread {
* \memory A small constant amount of memory to store the function. This
* memory is freed the thread is joined.
* \notthreadsafe
* \tparam Function
Type of callabl
e
* \tparam Function
Function object typ
e
*/
template
<
typename
Function
>
explicit
Thread
(
Function
function
/**< [IN] C
allable (without arguments, must be copyable)
*/
/**< [IN] C
opyable function object, callable without arguments
*/
);
/**
...
...
@@ -174,14 +174,14 @@ class Thread {
* \memory A small constant amount of memory to store the function. This
* memory is freed the thread is joined.
* \notthreadsafe
* \tparam Function
Type of callabl
e
* \tparam Function
Function object typ
e
*/
template
<
typename
Function
>
explicit
Thread
(
CoreSet
&
core_set
,
/**< [IN] Set of cores on which the thread shall be executed. */
Function
function
/**< [IN] C
allable (without arguments, must be copyable)
*/
/**< [IN] C
opyable function object, callable without arguments
*/
);
/**
...
...
@@ -196,13 +196,13 @@ class Thread {
* \memory A small constant amount of memory to store the function. This
* memory is freed the thread is joined.
* \notthreadsafe
* \tparam Function
Type of callabl
e
* \tparam Function
Function object typ
e
* \tparam Argument Type of argument
*/
template
<
typename
Function
,
typename
Arg
>
Thread
(
Function
function
,
/**< [IN] C
allable (with one argument, must be copyable)
*/
/**< [IN] C
opyable function object, callable with one argument
*/
Arg
arg
/**< [IN] Argument for function (must be copyable) */
);
...
...
@@ -219,14 +219,14 @@ class Thread {
* \memory A small constant amount of memory to store the function. This
* memory is freed the thread is joined.
* \notthreadsafe
* \tparam Function
Type of callabl
e
* \tparam Function
Function object typ
e
* \tparam Arg1 Type of first argument
* \tparam Arg2 Type of second argument
*/
template
<
typename
Function
,
typename
Arg1
,
typename
Arg2
>
Thread
(
Function
function
,
/**< [IN] C
allable (with two arguments, must be copyable)
*/
/**< [IN] C
opyable function object, callable with two arguments
*/
Arg1
arg1
,
/**< [IN] First argument for function (must be copyable) */
Arg2
arg2
...
...
base_cpp/include/embb/base/thread_specific_storage.h
View file @
ffa2f18a
...
...
@@ -35,12 +35,10 @@ namespace embb {
namespace
base
{
namespace
test
{
/**
* Forward declaration for friending.
*/
class
ThreadSpecificStorageTest
;
}
/**
...
...
base_cpp/include/embb/base/time.h
View file @
ffa2f18a
base_cpp/test/thread_test.h
View file @
ffa2f18a
...
...
@@ -43,8 +43,7 @@ class ThreadTest : public partest::TestCase {
/**
* Adds test methods.
*/
ThreadTest
();
/**<
number of threads concurrently running test methods */
ThreadTest
();
private
:
/**
...
...
dataflow_cpp/include/embb/dataflow/internal/inputs.h
View file @
ffa2f18a
...
...
@@ -89,7 +89,7 @@ class Inputs<Slices, T1, embb::base::internal::Nil, embb::base::internal::Nil,
const
int
idx
=
clock
%
Slices
;
if
(
count_
[
idx
]
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"All inputs already fired for this clock."
)
"All inputs already fired for this clock."
)
;
}
if
(
--
count_
[
idx
]
==
0
)
{
count_
[
idx
]
=
1
;
...
...
@@ -135,7 +135,7 @@ class Inputs<Slices, T1, T2, embb::base::internal::Nil,
const
int
idx
=
clock
%
Slices
;
if
(
count_
[
idx
]
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"All inputs already fired for this clock."
)
"All inputs already fired for this clock."
)
;
}
if
(
--
count_
[
idx
]
==
0
)
{
count_
[
idx
]
=
2
;
...
...
@@ -185,7 +185,7 @@ class Inputs<Slices, T1, T2, T3, embb::base::internal::Nil,
const
int
idx
=
clock
%
Slices
;
if
(
count_
[
idx
]
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"All inputs already fired for this clock."
)
"All inputs already fired for this clock."
)
;
}
if
(
--
count_
[
idx
]
==
0
)
{
count_
[
idx
]
=
3
;
...
...
@@ -238,7 +238,7 @@ class Inputs<Slices, T1, T2, T3, T4, embb::base::internal::Nil>
const
int
idx
=
clock
%
Slices
;
if
(
count_
[
idx
]
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"All inputs already fired for this clock."
)
"All inputs already fired for this clock."
)
;
}
if
(
--
count_
[
idx
]
==
0
)
{
count_
[
idx
]
=
4
;
...
...
@@ -296,7 +296,7 @@ class Inputs
const
int
idx
=
clock
%
Slices
;
if
(
count_
[
idx
]
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"All inputs already fired for this clock."
)
"All inputs already fired for this clock."
)
;
}
if
(
--
count_
[
idx
]
==
0
)
{
count_
[
idx
]
=
5
;
...
...
mtapi_c/include/embb/mtapi/c/mtapi.h
View file @
ffa2f18a
...
...
@@ -68,7 +68,7 @@
* </tr>
* <tr>
* <td>Action Function</td>
* <td>The
callable, an
executable function of an action, invoked by the
* <td>The executable function of an action, invoked by the
* MTAPI runtime when a task is started.</td>
* </tr>
* <tr>
...
...
mtapi_cpp/include/embb/mtapi/action.h
View file @
ffa2f18a
...
...
@@ -51,13 +51,13 @@ class Action {
}
/**
* Constructs an Action from any entity that provides an
* operator() (TaskContext &).
* Constructs an Action from a function object.
*
* \tparam Function Function object
*/
template
<
typename
Function
>
Action
(
Function
func
/**< [in] Anything that provides an
operator() (TaskContext &). */
Function
func
/**< [in] Function object */
)
:
function_
(
func
)
,
execution_policy_
()
{
...
...
@@ -65,13 +65,13 @@ class Action {
}
/**
* Constructs an Action from any entity that provides an
* operator() (TaskContext &) and an Affinity.
* Constructs an Action from a function object and an Affinity.
*
* \tparam Function Function object
*/
template
<
typename
Function
>
Action
(
Function
func
,
/**< [in] Anything that provides an
operator() (TaskContext &). */
Function
func
,
/**< [in] Function object */
ExecutionPolicy
execution_policy
/**< [in] Execution policy */
)
:
function_
(
func
)
...
...
mtapi_cpp/include/embb/mtapi/execution_policy.h
View file @
ffa2f18a
...
...
@@ -106,6 +106,13 @@ class ExecutionPolicy{
);
/**
* Returns the number of cores the policy is affine to.
*
* \return the number of cores
*/
unsigned
int
GetCoreCount
()
const
;
/**
* Returns the affinity
*
* \return the affinity
...
...
mtapi_cpp/include/embb/mtapi/node.h
View file @
ffa2f18a
...
...
@@ -129,6 +129,15 @@ class Node {
}
/**
* Returns the number of worker threads.
* \return The number of worker threads.
* \waitfree
*/
mtapi_uint_t
GetWorkerThreadCount
()
const
{
return
worker_thread_count_
;
}
/**
* Creates a Group to launch \link Task Tasks \endlink in.
* \return A reference to the created Group
* \throws ErrorException if the Group object could not be constructed.
...
...
@@ -210,6 +219,7 @@ class Node {
mtapi_task_context_t
*
context
);
mtapi_uint_t
core_count_
;
mtapi_uint_t
worker_thread_count_
;
mtapi_action_hndl_t
action_handle_
;
std
::
list
<
Queue
*>
queues_
;
std
::
list
<
Group
*>
groups_
;
...
...
mtapi_cpp/src/execution_policy.cc
View file @
ffa2f18a
...
...
@@ -27,6 +27,7 @@
#include <embb/mtapi/execution_policy.h>
#include <embb/mtapi/mtapi.h>
#include <embb/base/exceptions.h>
#include <embb/base/c/internal/bitset.h>
#include <cassert>
namespace
embb
{
...
...
@@ -105,6 +106,10 @@ bool ExecutionPolicy::IsSetWorker(mtapi_uint_t worker) {
return
MTAPI_TRUE
==
aff
;
}
unsigned
int
ExecutionPolicy
::
GetCoreCount
()
const
{
return
embb_bitset_count
(
&
affinity_
);
}
const
mtapi_affinity_t
&
ExecutionPolicy
::
GetAffinity
()
const
{
return
affinity_
;
}
...
...
mtapi_cpp/src/node.cc
View file @
ffa2f18a
...
...
@@ -75,6 +75,7 @@ Node::Node(
"mtapi::Node could not initialize mtapi"
);
}
core_count_
=
info
.
hardware_concurrency
;
worker_thread_count_
=
embb_core_set_count
(
&
attr
->
core_affinity
);
action_handle_
=
mtapi_action_create
(
MTAPI_CPP_TASK_JOB
,
action_func
,
MTAPI_NULL
,
0
,
MTAPI_NULL
,
&
status
);
if
(
MTAPI_SUCCESS
!=
status
)
{
...
...
partest.tar
100644 → 100755
View file @
ffa2f18a
No preview for this file type
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment