-
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
8e0e23b
to
a665253
Compare
Fixing the various CUDA issues right now. |
0a2d057
to
a722e7d
Compare
CarpetX/src/driver.hxx
Outdated
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.
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.
Fixed in 617d0d9
CarpetX/src/driver.hxx
Outdated
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
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.
Fixed in 617d0d9
CarpetX/src/driver.hxx
Outdated
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
.
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.
Moved into constructor code and / or added an assert
for the correct values. Those who compile with NDEBUG
are on their own. In 4fc6ceb
CarpetX/src/driver.hxx
Outdated
|
||
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 *
.
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.
Done in 3605564. Note that differs from AMReX's Array4D
and `GridPtrDesc1` class (and thus requires a const-cast somehwere in schedule.cxx)
For grid-functions:
```
auto &restrict groupdata = *leveldata.groupdata.at(gi);
const GridPtrDesc1 grid1(leveldata, groupdata, mfp);
for (int tl = 0; tl < int(groupdata.mfab.size()); ++tl) {
const amrex::Array4<CCTK_REAL> vars =
groupdata.mfab.at(tl)->array(mfp.index());
for (int vi = 0; vi < groupdata.numvars; ++vi)
cctkGH->data[groupdata.firstvarindex + vi][tl] = grid1.ptr(vars, vi);
}
```
For grid-arrays (and scalars):
```
auto &restrict arraygroupdata = *globaldata.arraygroupdata.at(gi);
for (int tl = 0; tl < int(arraygroupdata.data.size()); ++tl) {
const auto &restrict vars = arraygroupdata.data.at(tl);
for (int vi = 0; vi < arraygroupdata.numvars; ++vi)
cctkGH->data[arraygroupdata.firstvarindex + vi][tl] =
const_cast<void*>(vars.data_at(vi * arraygroupdata.array_size));
```
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.
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 not user triggerable (via parfile input) and the list is fixed by Cactus (not user or CarpetX code), so I'd rather keep the assert, if possible.
CarpetX/src/io_openpmd.cxx
Outdated
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.
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.
done in 49de23b
CarpetX/src/io_openpmd.cxx
Outdated
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.
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.
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
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.
CarpetX/src/io_openpmd.cxx
Outdated
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.
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.
Done in 016fec7
CarpetX/src/io_tsv.cxx
Outdated
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 *)
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.
Done in 4704af8
CarpetX/src/driver.cxx
Outdated
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 *)
.
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.
Done in 8f8fbad
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
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.
Since this is not user (parfile or other runtime input) triggerable and the list of allowed options is determined by the flesh and not the thorn being written (CarpetX) I'd rather keep the assert (since it's a bug) rather than the CCTK_Error
.
CarpetX/src/io_tsv.cxx
Outdated
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 *)
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.
Done in 4704af8
CarpetX/src/io_tsv.cxx
Outdated
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.
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.
It could, something like this:
```
for (int vi = 0; vi < arraygroupdata.numvars; ++vi)
file << sep;
const void *ptr = arraygroupdata.data.at(tl).data_at(np * vi + DI[out_dir] * i);
switch (cgroup.vartype) {
case CCTK_VARIABLE_REAL:
file << *(const CCTK_REAL *)ptr;
break;
case CCTK_VARIABLE_INT:
file << *(const CCTK_INT *)ptr;
break;
case CCTK_VARIABLE_COMPLEX: {
CCTK_COMPLEX value = *(const CCTK_COMPLEX *)ptr;
file << value.real() << sep << value.imag();
} break;
default:
assert(0 && "Unexpected variable type");
break;
}
file << "\n";
}
```
though it comes at the price of information about what is output being less local and requiring backtracking in the code when reading it.
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.
In addition to AnyVector
, you could introduce an AnyScalar
, and add a virtual function that outputs to a stream. (Not sure whether that makes the code simpler or more complex in the end.)
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.
Hmm, maybe. Not having all those switch
scattered around would be nice.
The tricky one is the CCTK_COMPLEX
output since it currently uses sep
which would not be known to AnyScalar::operator<<
.
Still an AnyScalar
and a AnyScalar AnyVector::operator[](size_t i) const
might be useful. Would be a return by value (at least unless I want to really complicate my life and have the AnyScalar carry a back-reference to its parent AnyVector
so that assignment to it would change the AnyVector
element) for now.
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.
Something like 98ab37c ? So far only used for output. Could possibly also be used for setting poison values (though there performance issues may show up).
CarpetX/src/valid.cxx
Outdated
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 does not complain about the varuable sized array, but it does in io_openpmd.cxx. I have no clue why.
I will redo this all anyway, to have one poison code for both places where it is used.
CarpetX/src/valid.cxx
Outdated
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
?
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.
removed in 1834168
CarpetX/src/valid.cxx
Outdated
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.
done in 49de23b
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.
used clang-format-16 -style file -i
3ab11f1
to
b5f228f
Compare
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: