Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
IP
elsa
Commits
6556c6b1
Commit
6556c6b1
authored
Mar 17, 2020
by
Jens Petit
Browse files
DataHandlerGPU: Assignment operation of DataContainer (
#21
)
parent
57aadf80
Changes
3
Hide whitespace changes
Inline
Side-by-side
elsa/core/DataContainer.cpp
View file @
6556c6b1
...
...
@@ -47,13 +47,12 @@ namespace elsa
if
(
this
!=
&
other
)
{
_dataDescriptor
=
other
.
_dataDescriptor
->
clone
();
if
(
_dataHandler
)
{
if
(
_dataHandler
&&
canAssign
(
other
.
_dataHandlerType
)
)
{
*
_dataHandler
=
*
other
.
_dataHandler
;
}
else
{
_dataHandler
=
other
.
_dataHandler
->
clone
();
_dataHandlerType
=
other
.
_dataHandlerType
;
}
// TODO: Check what to do with handler type if CPU copy assign to GPU type
}
return
*
this
;
...
...
@@ -75,14 +74,13 @@ namespace elsa
{
_dataDescriptor
=
std
::
move
(
other
.
_dataDescriptor
);
if
(
_dataHandler
)
{
if
(
_dataHandler
&&
canAssign
(
other
.
_dataHandlerType
)
)
{
*
_dataHandler
=
std
::
move
(
*
other
.
_dataHandler
);
}
else
{
_dataHandler
=
std
::
move
(
other
.
_dataHandler
);
_dataHandlerType
=
std
::
move
(
other
.
_dataHandlerType
);
}
// TODO: Check what to do with handler type if CPU move assign to GPU type
// leave other in a valid state
other
.
_dataDescriptor
=
nullptr
;
other
.
_dataHandler
=
nullptr
;
...
...
@@ -428,6 +426,71 @@ namespace elsa
return
_dataHandlerType
;
}
template
<
typename
data_t
>
DataContainer
<
data_t
>
DataContainer
<
data_t
>::
loadToCPU
()
{
if
(
_dataHandlerType
==
DataHandlerType
::
CPU
||
_dataHandlerType
==
DataHandlerType
::
MAP_CPU
)
{
throw
std
::
logic_error
(
"DataContainer: cannot load data to CPU with already CPU based container"
);
}
DataContainer
<
data_t
>
dcCPU
(
*
_dataDescriptor
,
DataHandlerType
::
CPU
);
for
(
index_t
i
=
0
;
i
<
getSize
();
i
++
)
{
dcCPU
[
i
]
=
this
->
operator
[](
i
);
}
return
dcCPU
;
}
template
<
typename
data_t
>
DataContainer
<
data_t
>
DataContainer
<
data_t
>::
loadToGPU
()
{
if
(
_dataHandlerType
==
DataHandlerType
::
GPU
||
_dataHandlerType
==
DataHandlerType
::
MAP_GPU
)
{
throw
std
::
logic_error
(
"DataContainer: cannot load data to GPU with already GPU based container"
);
}
DataContainer
<
data_t
>
dcGPU
(
*
_dataDescriptor
,
DataHandlerType
::
GPU
);
for
(
index_t
i
=
0
;
i
<
getSize
();
i
++
)
{
dcGPU
[
i
]
=
this
->
operator
[](
i
);
}
return
dcGPU
;
}
template
<
typename
data_t
>
bool
DataContainer
<
data_t
>::
canAssign
(
DataHandlerType
handlerType
)
{
if
(
_dataHandlerType
==
DataHandlerType
::
CPU
||
_dataHandlerType
==
DataHandlerType
::
MAP_CPU
)
{
switch
(
handlerType
)
{
case
DataHandlerType
::
CPU
:
return
true
;
break
;
case
DataHandlerType
::
MAP_CPU
:
return
true
;
break
;
default:
return
false
;
}
}
else
{
switch
(
handlerType
)
{
case
DataHandlerType
::
GPU
:
return
true
;
break
;
case
DataHandlerType
::
MAP_GPU
:
return
true
;
break
;
default:
return
false
;
}
}
}
// ------------------------------------------
// explicit template instantiation
template
class
DataContainer
<
float
>;
...
...
elsa/core/DataContainer.h
View file @
6556c6b1
...
...
@@ -72,6 +72,10 @@ namespace elsa
* \brief copy assignment for DataContainer
*
* \param[in] other DataContainer to copy
*
* Note that a copy assignment with a DataContainer on a different device (CPU vs GPU) will
* result in an "infectious" copy which means that afterwards the current container will use
* the same device as "other".
*/
DataContainer
<
data_t
>&
operator
=
(
const
DataContainer
<
data_t
>&
other
);
...
...
@@ -94,6 +98,10 @@ namespace elsa
* The moved-from objects remains in a valid state. However, as preconditions are not
* fulfilled for any member functions, the object should not be used. After move- or copy-
* assignment, this is possible again.
*
* Note that a copy assignment with a DataContainer on a different device (CPU vs GPU) will
* result in an "infectious" copy which means that afterwards the current container will use
* the same device as "other".
*/
DataContainer
<
data_t
>&
operator
=
(
DataContainer
<
data_t
>&&
other
);
...
...
@@ -371,6 +379,26 @@ namespace elsa
template
<
bool
GPU
,
class
Operand
,
std
::
enable_if_t
<
isDataContainer
<
Operand
>,
int
>>
friend
constexpr
auto
evaluateOrReturn
(
Operand
const
&
operand
);
/**
* \brief Factory function which returns GPU based DataContainers
*
* \return the GPU based DataContainer
*
* Note that if this function is called on a container which is already GPU based, it will
* throw an exception.
*/
DataContainer
loadToGPU
();
/**
* \brief Factory function which returns CPU based DataContainers
*
* \return the CPU based DataContainer
*
* Note that if this function is called on a container which is already CPU based, it will
* throw an exception.
*/
DataContainer
loadToCPU
();
private:
/// the current DataDescriptor
std
::
unique_ptr
<
DataDescriptor
>
_dataDescriptor
;
...
...
@@ -391,6 +419,20 @@ namespace elsa
explicit
DataContainer
(
const
DataDescriptor
&
dataDescriptor
,
std
::
unique_ptr
<
DataHandler
<
data_t
>>
dataHandler
,
DataHandlerType
dataType
=
defaultHandlerType
);
/**
* \brief Helper function to indicate if a regular assignment or a clone should be performed
*
* \param[in] handlerType the member variable of the other container in
* copy-/move-assignment
*
* \return true if a regular assignment of the pointed to DataHandlers should be done
*
* An assignment operation with a DataContainer which does not use the same device (CPU /
* GPU) has to be handled differently. This helper function indicates if a regular
* assignment should be performed or not.
*/
bool
canAssign
(
DataHandlerType
handlerType
);
};
/// User-defined template argument deduction guide for the expression based constructor
...
...
elsa/core/tests/test_DataContainer.cpp
View file @
6556c6b1
...
...
@@ -587,6 +587,92 @@ TEMPLATE_PRODUCT_TEST_CASE("Scenario: Testing creation of Maps through DataConta
}
}
#ifdef ELSA_CUDA_VECTOR
TEMPLATE_TEST_CASE
(
"Scenario: Testing loading data to GPU and vice versa."
,
""
,
float
,
double
,
std
::
complex
<
float
>
,
std
::
complex
<
double
>
,
index_t
)
{
GIVEN
(
"A CPU DataContainer with random data"
)
{
IndexVector_t
numCoeff
(
3
);
numCoeff
<<
52
,
7
,
29
;
DataDescriptor
desc
(
numCoeff
);
DataContainer
<
TestType
>
dcCPU
(
desc
,
DataHandlerType
::
CPU
);
DataContainer
<
TestType
>
dcGPU
(
desc
,
DataHandlerType
::
GPU
);
Eigen
::
Matrix
<
TestType
,
Eigen
::
Dynamic
,
1
>
randVec
{
dcCPU
.
getSize
()};
randVec
.
setRandom
();
for
(
index_t
i
=
0
;
i
<
dcCPU
.
getSize
();
++
i
)
{
dcCPU
[
i
]
=
randVec
(
i
);
dcGPU
[
i
]
=
randVec
(
i
);
}
WHEN
(
"Trying to call loadToCPU on CPU container"
)
{
THEN
(
"Throws"
)
{
REQUIRE_THROWS
(
dcCPU
.
loadToCPU
());
}
}
WHEN
(
"Trying to call loadToGPU on GPU container"
)
{
THEN
(
"Throws"
)
{
REQUIRE_THROWS
(
dcGPU
.
loadToGPU
());
}
}
WHEN
(
"Loading to GPU from CPU"
)
{
DataContainer
dcGPU2
=
dcCPU
.
loadToGPU
();
REQUIRE
(
dcGPU2
.
getDataHandlerType
()
==
DataHandlerType
::
GPU
);
THEN
(
"all elements have to be the same"
)
{
for
(
index_t
i
=
0
;
i
<
dcCPU
.
getSize
();
++
i
)
{
REQUIRE
(
dcGPU2
[
i
]
==
dcGPU
[
i
]);
}
}
}
WHEN
(
"Loading to CPU from GPU"
)
{
DataContainer
dcCPU2
=
dcGPU
.
loadToCPU
();
REQUIRE
(
dcCPU2
.
getDataHandlerType
()
==
DataHandlerType
::
CPU
);
THEN
(
"all elements have to be the same"
)
{
for
(
index_t
i
=
0
;
i
<
dcCPU
.
getSize
();
++
i
)
{
REQUIRE
(
dcCPU2
[
i
]
==
dcGPU
[
i
]);
}
}
}
WHEN
(
"copy-assigning a GPU to a CPU container"
)
{
dcCPU
=
dcGPU
;
THEN
(
"it should be a GPU container"
)
{
REQUIRE
(
dcCPU
.
getDataHandlerType
()
==
DataHandlerType
::
GPU
);
}
AND_THEN
(
"they should be equal"
)
{
REQUIRE
(
dcCPU
==
dcGPU
);
}
}
WHEN
(
"copy-assigning a CPU to a GPU container"
)
{
dcGPU
=
dcCPU
;
THEN
(
"it should be a GPU container"
)
{
REQUIRE
(
dcGPU
.
getDataHandlerType
()
==
DataHandlerType
::
CPU
);
}
AND_THEN
(
"they should be equal"
)
{
REQUIRE
(
dcCPU
==
dcGPU
);
}
}
}
}
#endif
SCENARIO
(
"Testing iterators for DataContainer"
)
{
GIVEN
(
"A 1D container"
)
...
...
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