-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a small class to create a class instance on device.
And a unit test for it. It is not just creating a device object but a virtual class instance on device and then invoking a virtual function through the base class on device. This is meant to be a simple example and the start of the discussion on how to structure the code for future development of GPU enabled Kokkos kernels.
- Loading branch information
Showing
4 changed files
with
124 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#ifndef CREATEDEVICEEXPRESSION_H | ||
#define CREATEDEVICEEXPRESSION_H | ||
|
||
#include <type_traits> | ||
|
||
#include <KokkosInterface.h> | ||
|
||
namespace sierra { | ||
namespace nalu { | ||
|
||
template <typename T> | ||
inline | ||
T* create_device_expression(const T & rhs) | ||
{ | ||
const std::string debuggingName(typeid(T).name()); | ||
T* t = kokkos_malloc_on_device<T>(debuggingName); | ||
// Bring rhs into local scope for capture to device. | ||
const T RHS(rhs); | ||
kokkos_parallel_for(debuggingName, 1, [&] (const int i) { | ||
new (t) T(RHS); | ||
}); | ||
return t; | ||
} | ||
} // namespace nalu | ||
} // namespace sierra | ||
|
||
#endif /* CREATEDEVICEEXPRESSION_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#include <gtest/gtest.h> | ||
|
||
#include "UnitTestUtils.h" | ||
|
||
|
||
#include <string> | ||
#include <iostream> | ||
#include <vector> | ||
|
||
#include <KokkosInterface.h> | ||
#include "utils/CreateDeviceExpression.h" | ||
|
||
class deviceable { | ||
protected : | ||
deviceable *DeviceCopy; | ||
public : | ||
KOKKOS_FORCEINLINE_FUNCTION deviceable() : DeviceCopy(nullptr) {} | ||
virtual ~deviceable() { | ||
if (DeviceCopy) delete_device_copy(); | ||
DeviceCopy = nullptr; | ||
} | ||
template <class T> void copy_to_device(const T &t) { | ||
DeviceCopy = sierra::nalu::create_device_expression(t); | ||
} | ||
void delete_device_copy() { | ||
sierra::nalu::kokkos_free_on_device(DeviceCopy); | ||
} | ||
template<class T> T* device_copy() const {return dynamic_cast<T*>(DeviceCopy);} | ||
}; | ||
|
||
class shape : public deviceable { | ||
public : | ||
KOKKOS_FORCEINLINE_FUNCTION shape() {} | ||
virtual ~shape() {} | ||
virtual double area() const = 0; | ||
}; | ||
|
||
class rectangle : public shape { | ||
const double L,W; | ||
public : | ||
KOKKOS_FORCEINLINE_FUNCTION rectangle(const double l,const double w):shape(),L(l),W(w) { | ||
copy_to_device(*this); | ||
} | ||
KOKKOS_FORCEINLINE_FUNCTION rectangle(const rectangle &r):shape(),L(r.L),W(r.W) {} | ||
virtual ~rectangle(){} | ||
virtual double area() const final { | ||
return L*W; | ||
} | ||
}; | ||
|
||
class circle : public shape { | ||
const double R; | ||
public : | ||
KOKKOS_FORCEINLINE_FUNCTION circle(const double r):shape(),R(r) { | ||
copy_to_device(*this); | ||
} | ||
KOKKOS_FORCEINLINE_FUNCTION circle(const circle &c):shape(),R(c.R) {} | ||
virtual ~circle(){} | ||
virtual double area() const final { | ||
return 2*3.14159265*R; | ||
} | ||
}; | ||
|
||
|
||
TEST(CreateDeviceExpression, shapes) | ||
{ | ||
// Create a couple of virtual classes on host and device. | ||
shape *r = new rectangle(4,5); | ||
shape *c = new circle(2); | ||
shape *r_dev = r->device_copy<shape>(); | ||
shape *c_dev = c->device_copy<shape>(); | ||
|
||
double r_area; | ||
auto r_on_device = [&] (int i, double &a) { | ||
a = r_dev->area(); | ||
}; | ||
sierra::nalu::kokkos_parallel_reduce(1, r_on_device, r_area, "Call Rectangle on Device."); | ||
|
||
double c_area; | ||
auto c_on_device = [&] (int i, double &a) { | ||
a = c_dev->area(); | ||
}; | ||
sierra::nalu::kokkos_parallel_reduce(1, c_on_device, c_area, "Call Circle on Device."); | ||
|
||
EXPECT_EQ(r_area, r->area()) << "Area of a 4x5 rectangle on device and host"; | ||
EXPECT_EQ(c_area, c->area()) << "Area of a radius 2 circle on device and host"; | ||
|
||
delete r; | ||
delete c; | ||
} | ||
|