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
ca032936
authored
Feb 26, 2015
by
Tobias Fuchs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
algorithms_cpp: Fix and cleanup of MergeSort
parent
2f755525
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
58 additions
and
70 deletions
+58
-70
algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h
+1
-1
algorithms_cpp/include/embb/algorithms/internal/merge_sort-inl.h
+57
-69
algorithms_cpp/include/embb/algorithms/merge_sort.h
+0
-0
No files found.
algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h
View file @
ca032936
...
@@ -116,7 +116,7 @@ void ForEachRecursive(RAI first, RAI last, Function unary,
...
@@ -116,7 +116,7 @@ void ForEachRecursive(RAI first, RAI last, Function unary,
block_size
=
1
;
block_size
=
1
;
}
}
}
}
//
Perform check of
task number sufficiency
//
Check
task number sufficiency
if
(((
distance
/
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
,
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Not enough MTAPI tasks available for parallel foreach"
);
"Not enough MTAPI tasks available for parallel foreach"
);
...
...
algorithms_cpp/include/embb/algorithms/internal/merge_sort-inl.h
View file @
ca032936
...
@@ -60,22 +60,13 @@ class MergeSortFunctor {
...
@@ -60,22 +60,13 @@ class MergeSortFunctor {
}
}
void
Action
(
mtapi
::
TaskContext
&
)
{
void
Action
(
mtapi
::
TaskContext
&
)
{
typedef
typename
std
::
iterator_traits
<
RAI
>::
difference_type
difference_type
;
size_t
chunk_split_index
=
(
chunk_first_
+
chunk_last_
)
/
2
;
size_t
chunk_split_index
=
(
chunk_first_
+
chunk_last_
)
/
2
;
if
(
chunk_first_
==
chunk_last_
)
{
if
(
chunk_first_
==
chunk_last_
)
{
// Leaf case: recurse into a single chunk's elements:
// Leaf case: recurse into a single chunk's elements:
ChunkDescriptor
<
RAI
>
chunk
=
partitioner_
[
chunk_first_
];
ChunkDescriptor
<
RAI
>
chunk
=
partitioner_
[
chunk_first_
];
MergeSortChunkFunctor
functor
(
chunk
.
GetFirst
(),
MergeSortChunk
(
chunk
.
GetFirst
(),
chunk
.
GetLast
(),
depth_
);
chunk
.
GetLast
(),
}
else
{
temp_first_
,
// Recurse further, split chunks:
global_first_
,
depth_
);
functor
.
Action
();
return
;
}
// Recurse further:
// Split chunks into left / right branches:
self_t
functor_l
(
chunk_first_
,
self_t
functor_l
(
chunk_first_
,
chunk_split_index
,
chunk_split_index
,
temp_first_
,
temp_first_
,
...
@@ -101,7 +92,8 @@ class MergeSortFunctor {
...
@@ -101,7 +92,8 @@ class MergeSortFunctor {
ChunkDescriptor
<
RAI
>
chunk_f
=
partitioner_
[
chunk_first_
];
ChunkDescriptor
<
RAI
>
chunk_f
=
partitioner_
[
chunk_first_
];
ChunkDescriptor
<
RAI
>
chunk_m
=
partitioner_
[
chunk_split_index
+
1
];
ChunkDescriptor
<
RAI
>
chunk_m
=
partitioner_
[
chunk_split_index
+
1
];
ChunkDescriptor
<
RAI
>
chunk_l
=
partitioner_
[
chunk_last_
];
ChunkDescriptor
<
RAI
>
chunk_l
=
partitioner_
[
chunk_last_
];
if
(
CloneBackToInput
())
{
if
(
CloneBackToInput
(
depth_
))
{
// Merge from temp into input:
difference_type
first
=
std
::
distance
(
global_first_
,
chunk_f
.
GetFirst
());
difference_type
first
=
std
::
distance
(
global_first_
,
chunk_f
.
GetFirst
());
difference_type
mid
=
std
::
distance
(
global_first_
,
chunk_m
.
GetFirst
());
difference_type
mid
=
std
::
distance
(
global_first_
,
chunk_m
.
GetFirst
());
difference_type
last
=
std
::
distance
(
global_first_
,
chunk_l
.
GetLast
());
difference_type
last
=
std
::
distance
(
global_first_
,
chunk_l
.
GetLast
());
...
@@ -109,86 +101,77 @@ class MergeSortFunctor {
...
@@ -109,86 +101,77 @@ class MergeSortFunctor {
chunk_f
.
GetFirst
(),
chunk_f
.
GetFirst
(),
comparison_
);
comparison_
);
}
else
{
}
else
{
// Merge from input into temp:
SerialMerge
(
chunk_f
.
GetFirst
(),
chunk_m
.
GetFirst
(),
chunk_l
.
GetLast
(),
SerialMerge
(
chunk_f
.
GetFirst
(),
chunk_m
.
GetFirst
(),
chunk_l
.
GetLast
(),
temp_first_
+
std
::
distance
(
global_first_
,
chunk_f
.
GetFirst
()),
temp_first_
+
std
::
distance
(
global_first_
,
chunk_f
.
GetFirst
()),
comparison_
);
comparison_
);
}
}
}
}
/**
* Determines the input and output arrays for one level in merge sort.
*
* \return \c true if the temporary data range is input and the array to be
* sorted is output. \c false, if the other way around.
*/
bool
CloneBackToInput
()
{
return
depth_
%
2
==
0
?
true
:
false
;
}
}
private
:
typedef
MergeSortFunctor
<
RAI
,
RAITemp
,
ComparisonFunction
>
self_t
;
private
:
/**
/**
*
Non-parallelized part of merge sort on
elements within a single chunk.
*
Serial merge sort of
elements within a single chunk.
*/
*/
class
MergeSortChunkFunctor
{
void
MergeSortChunk
(
RAI
first
,
public
:
RAI
last
,
MergeSortChunkFunctor
(
RAI
first
,
RAI
last
,
int
depth
)
{
RAITemp
temp_first
,
const
RAI
&
global_first
,
int
depth
)
:
first_
(
first
),
last_
(
last
),
temp_first_
(
temp_first
),
global_first_
(
global_first
),
depth_
(
depth
)
{
}
void
Action
()
{
size_t
distance
=
static_cast
<
size_t
>
(
size_t
distance
=
static_cast
<
size_t
>
(
std
::
distance
(
first_
,
last_
));
std
::
distance
(
first
,
last
));
if
(
distance
<=
1
)
{
if
(
distance
<=
1
)
{
// Leaf case:
// Leaf case:
if
(
!
CloneBackToInput
(
)
&&
distance
!=
0
)
{
if
(
!
CloneBackToInput
(
depth
)
&&
distance
!=
0
)
{
RAITemp
temp_first
=
temp_first_
;
RAITemp
temp_first
=
temp_first_
;
std
::
advance
(
temp_first
,
std
::
distance
(
global_first_
,
first_
));
std
::
advance
(
temp_first
,
std
::
distance
(
global_first_
,
first
));
*
temp_first
=
*
first_
;
*
temp_first
=
*
first
;
}
}
return
;
return
;
}
}
// Recurse further. Use binary split, ignoring chunk size as this
// Recurse further. Use binary split, ignoring chunk size as this
// recursion is serial
:
// recursion is serial and has leaf size 1
:
ChunkPartitioner
<
RAI
>
partitioner
(
first_
,
last_
,
2
);
ChunkPartitioner
<
RAI
>
partitioner
(
first
,
last
,
2
);
ChunkDescriptor
<
RAI
>
chunk_l
=
partitioner
[
0
];
ChunkDescriptor
<
RAI
>
chunk_l
=
partitioner
[
0
];
ChunkDescriptor
<
RAI
>
chunk_r
=
partitioner
[
1
];
ChunkDescriptor
<
RAI
>
chunk_r
=
partitioner
[
1
];
MergeSortChunkFunctor
functor_l
(
MergeSortChunk
(
chunk_l
.
GetFirst
(),
chunk_l
.
GetFirst
(),
chunk_l
.
GetLast
(),
chunk_l
.
GetLast
(),
temp_first_
,
global_first_
,
depth_
+
1
);
depth
+
1
);
MergeSortChunkFunctor
functor_r
(
MergeSortChunk
(
chunk_r
.
GetFirst
(),
chunk_r
.
GetFirst
(),
chunk_r
.
GetLast
(),
chunk_r
.
GetLast
(),
temp_first_
,
global_first_
,
depth_
+
1
);
depth
+
1
);
functor_l
.
Action
();
if
(
CloneBackToInput
(
depth
))
{
functor_r
.
Action
();
// Merge from temp into input:
difference_type
d_first
=
std
::
distance
(
global_first_
,
chunk_l
.
GetFirst
());
difference_type
d_mid
=
std
::
distance
(
global_first_
,
chunk_r
.
GetFirst
());
difference_type
d_last
=
std
::
distance
(
global_first_
,
chunk_r
.
GetLast
());
SerialMerge
(
temp_first_
+
d_first
,
temp_first_
+
d_mid
,
temp_first_
+
d_last
,
chunk_l
.
GetFirst
(),
comparison_
);
}
else
{
// Merge from input into temp:
SerialMerge
(
chunk_l
.
GetFirst
(),
chunk_r
.
GetFirst
(),
chunk_r
.
GetLast
(),
temp_first_
+
std
::
distance
(
global_first_
,
chunk_l
.
GetFirst
()),
comparison_
);
}
}
}
private
:
/**
/**
* Determines the input and output arrays for one level in merge sort.
* Determines the input and output arrays for one level in merge sort.
*
*
* \return \c true if the temporary data range is input and the array to be
* \return \c true if the temporary data range is input and the array to be
* sorted is output. \c false, if the other way around.
* sorted is output. \c false, if the other way around.
*/
*/
bool
CloneBackToInput
(
)
{
bool
CloneBackToInput
(
int
depth
)
{
return
depth_
%
2
==
0
?
true
:
false
;
return
depth
%
2
==
0
?
true
:
false
;
}
}
RAI
first_
;
private
:
RAI
last_
;
typedef
MergeSortFunctor
<
RAI
,
RAITemp
,
ComparisonFunction
>
self_t
;
RAITemp
temp_first_
;
typedef
typename
std
::
iterator_traits
<
RAI
>::
difference_type
RAI
global_first_
;
difference_type
;
int
depth_
;
};
private
:
private
:
size_t
chunk_first_
;
size_t
chunk_first_
;
...
@@ -243,24 +226,27 @@ void MergeSort(
...
@@ -243,24 +226,27 @@ void MergeSort(
size_t
block_size
size_t
block_size
)
{
)
{
typedef
typename
std
::
iterator_traits
<
RAI
>::
difference_type
difference_type
;
typedef
typename
std
::
iterator_traits
<
RAI
>::
difference_type
difference_type
;
typedef
internal
::
MergeSortFunctor
<
RAI
,
RAITemp
,
ComparisonFunction
>
functor_t
;
difference_type
distance
=
std
::
distance
(
first
,
last
);
if
(
distance
==
0
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Distance for ForEach is 0"
);
}
embb
::
mtapi
::
Node
&
node
=
embb
::
mtapi
::
Node
::
GetInstance
();
embb
::
mtapi
::
Node
&
node
=
embb
::
mtapi
::
Node
::
GetInstance
();
difference_type
distance
=
last
-
first
;
// Determine actually used block size
assert
(
distance
>=
0
);
if
(
block_size
==
0
)
{
if
(
block_size
==
0
)
{
block_size
=
(
static_cast
<
size_t
>
(
distance
)
/
node
.
GetCoreCount
());
block_size
=
(
static_cast
<
size_t
>
(
distance
)
/
node
.
GetCoreCount
());
if
(
block_size
==
0
)
if
(
block_size
==
0
)
block_size
=
1
;
block_size
=
1
;
}
}
if
(((
distance
/
block_size
)
*
2
)
+
1
>
MTAPI_NODE_MAX_TASKS_DEFAULT
)
{
// Check task number sufficiency
if
(((
distance
/
block_size
)
*
2
)
+
1
>
MTAPI_NODE_MAX_TASKS_DEFAULT
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Not enough MTAPI tasks available to perform
the
merge sort"
);
"Not enough MTAPI tasks available to perform merge sort"
);
}
}
internal
::
BlockSizePartitioner
<
RAI
>
partitioner
(
first
,
last
,
block_size
);
internal
::
BlockSizePartitioner
<
RAI
>
partitioner
(
first
,
last
,
block_size
);
functor_t
functor
(
0
,
internal
::
MergeSortFunctor
<
RAI
,
RAITemp
,
ComparisonFunction
>
functor
(
partitioner
.
Size
()
-
1
,
0
,
partitioner
.
Size
()
-
1
,
temporary_first
,
temporary_first
,
comparison
,
comparison
,
policy
,
policy
,
...
@@ -268,12 +254,14 @@ void MergeSort(
...
@@ -268,12 +254,14 @@ void MergeSort(
first
,
first
,
0
);
0
);
mtapi
::
Task
task
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor
,
mtapi
::
Task
task
=
node
.
Spawn
(
mtapi
::
Action
(
base
::
MakeFunction
(
functor
,
&
internal
::
MergeSortFunctor
<
RAI
,
RAITemp
,
ComparisonFunction
>
::
Action
),
&
functor_t
::
Action
),
policy
));
policy
));
task
.
Wait
(
MTAPI_INFINITE
);
task
.
Wait
(
MTAPI_INFINITE
);
}
}
// @NOTE: Why is there no type guard for RAI?
}
// namespace algorithms
}
// namespace algorithms
}
// namespace embb
}
// namespace embb
...
...
algorithms_cpp/include/embb/algorithms/merge_sort.h
View file @
ca032936
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