-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add support for different data types in arrays, also on GPU #324
base: main
Are you sure you want to change the base?
Conversation
e76a479
to
5a5e74c
Compare
5a5e74c
to
8e0e23b
Compare
8e0e23b
to
a665253
Compare
Fixing the various CUDA issues right now. |
0a2d057
to
a722e7d
Compare
AnyTypeVector(const AnyTypeVector &) = delete; | ||
AnyTypeVector &operator=(const AnyTypeVector &) = delete; | ||
AnyTypeVector &operator=(const AnyTypeVector &&other) { | ||
this->_type = other._type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect. The moved-from object will still have its destructor called, which would deallocate the memory. The moved-from object needs to be put into an "inactive" state.
return *this; | ||
} | ||
AnyTypeVector(AnyTypeVector &&other) | ||
: _type(other._type), _data(other._data), _count(other._count) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
AnyTypeVector() : _type(-1), _data(nullptr), _count(0){}; | ||
AnyTypeVector(int type_, size_t count_) | ||
: _type(type_), | ||
_data(amrex::The_Arena()->alloc(CCTK_VarTypeSize(type_) * count_)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks dangerous. Passing an invalid type
makes CCTK_VarTypeSize
return a negative number, and C++ will convert this into a very large unsigned number for alloc
. Better to check and call CCTK_ERROR
.
|
||
int type() const { return _type; }; | ||
|
||
void *data_at(size_t i) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should probably be two versions of this function, one const
and returning a const void*
, and the other non-const and returning a void *
.
static_cast<CCTK_COMPLEX *>(cactus_var_ptr), start, count); | ||
break; | ||
default: | ||
assert(0 && "Unexpected variable type"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd call CCTK_ERROR
here because it can't be disabled by compiler options.
std::vector<char> poison(typesize); | ||
// for int: deadbeef for little endian machines | ||
for (size_t i = 0; i < typesize; i += sizeof poison) | ||
std::memcpy(&poison[i], &ipoison, std::min(poison.size(), typesize - i)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would define three different poison values here (for int, real, and complex). Using just some of the real
bits for int
might give values that aren't very distinctive. I found that large positive values make for good integer poison. Negative values don't work that well because they are more likely to be clipped off.
start, count); | ||
break; | ||
default: | ||
assert(0 && "Unexpected variable type"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call CCTK_ERROR
here.
case CCTK_VARIABLE_COMPLEX: | ||
return openPMD::determineDatatype<CCTK_COMPLEX>(); | ||
default: | ||
assert(0 && "Unexpected varType"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CCTK_ERROR
switch (cgroup.vartype) { | ||
case CCTK_VARIABLE_REAL: | ||
record_components.at(vi).storeChunkRaw( | ||
static_cast<CCTK_REAL const *const>(var_ptr), start, count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be static_cast<CCTK_REAL const *>
, the additional const
doesn't have any effect since the pointer is an rvalue.
file << sep << arraygroupdata.data.at(tl).at(vi); | ||
switch (cgroup.vartype) { | ||
case CCTK_VARIABLE_REAL: | ||
file << sep << *(CCTK_REAL *)arraygroupdata.data.at(tl).data_at(vi); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be (const CCTK_REAL *)
for (size_t i = 0; i < anytypevector.size(); ++i) { | ||
switch (anytypevector.type()) { | ||
case CCTK_VARIABLE_COMPLEX: | ||
yaml << *(CCTK_COMPLEX *)anytypevector.data_at(i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be (const CCTK_COMPLEX *)
.
file << sep << col++ << ":" << varname << ".real"; | ||
file << sep << col++ << ":" << varname << ".imag"; | ||
} else | ||
assert(0 && "Unexpected variable type"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better call CCTK_ERROR
switch (cgroup.vartype) { | ||
case CCTK_VARIABLE_REAL: | ||
file << sep | ||
<< *(CCTK_REAL *)arraygroupdata.data.at(tl).data_at( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(const CCTK_REAL *)
break; | ||
case CCTK_VARIABLE_INT: | ||
file << sep | ||
<< *(CCTK_INT *)arraygroupdata.data.at(tl).data_at( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression arraygroupdata.data.at(tl).data_at(np * vi + DI[out_dir] * i)
could be calculated before the switch
statement to reduce code duplication.
CCTK_REAL poison; | ||
std::memcpy(&poison, &ipoison, sizeof poison); | ||
const size_t typesize = size_t(CCTK_VarTypeSize(group.vartype)); | ||
char poison[typesize]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't you switch to std::vector
elsewhere for a similar construct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and here it dies not complain about the varuable sized array, but it diez in io_openpmd.cxx. I have no clue why.
I will redo thus all anyway, to have one poision code for bith places where it is used.
CCTK_REAL poison; | ||
std::memcpy(&poison, &ipoison, sizeof poison); | ||
const size_t typesize = size_t(CCTK_VarTypeSize(group.vartype)); | ||
char poison[typesize]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::vector
?
using std::isnan; | ||
if (CCTK_BUILTIN_EXPECT(nan_handling == nan_handling_t::allow_nans | ||
? std::memcmp(ptr, poison, sizeof *ptr) == 0 | ||
: isnan(*ptr), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could call isnan(real) || isnan(imag)
for complex numbers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess, yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left a few comments. Some are important and need to be addressed. Most are suggestions.
This adds proper support for data types other than
double
to CarpetX, also for GPUs.It introduces a helper class
AnyVector
that can hold any data type (similar togdata
in CarpetLib), as well as a number of switch statements to handle openPMD's typed output routines.I am told that very new versions of openPMD-api lets one call the internal un-typed output routine, but at the time this code was written, that was not yet possible, and thus may not be possible on all cluster installed copies of openPMD.
Python code to dump data to compare: