Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/amrex/extensions/ArrayOfStructs.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ def aos_to_numpy(self, copy=False):
if copy:
# This supports a device-to-host copy.
#
# todo: validate of the to_host() returned object
# lifetime is always managed correctly by
# Python's GC - otherwise copy twice via copy=True
return np.array(self.to_host(), copy=False)
# The to_host() returned object is a temporary, and
# np.array using the __array_interface__ protocol does
# not keep it alive automatically unless it is stored
# in an actual variable (tmp).
tmp = self.to_host()
ret = np.array(tmp, copy=False)
assert ret.base is tmp
return ret
else:
return np.array(self, copy=False)

Expand Down
12 changes: 8 additions & 4 deletions src/amrex/extensions/PODVector.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ def podvector_to_numpy(self, copy=False):
if copy:
Copy link
Member Author

@ax3l ax3l Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can generally make this a bit more explicit by checking if self is on GPU and otherwise just copying from it directly, with another if/else branch. But the logic here should have the same effect and amount of copies involved...

The only difference is that here we will always end up with pinned memory, while we might be sometimes interested using regular host memory. But seems niche.

# This supports a device-to-host copy.
#
# todo: validate of the to_host() returned object
# lifetime is always managed correctly by
# Python's GC - otherwise copy twice via copy=True
return np.array(self.to_host(), copy=False)
# The to_host() returned object is a temporary, and
# np.array using the __array_interface__ protocol does
# not keep it alive automatically unless it is stored
# in an actual variable (tmp).
tmp = self.to_host()
Copy link
Member Author

@ax3l ax3l Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, looks like there is more / this is not a sufficient fix (at least for some SP tests on conda-forge):
conda-forge/impactx-feedstock#56 (comment)

It already has an issue here, so the problem could be in the implementation of to_host()...
https://github.com/AMReX-Codes/pyamrex/blob/25.09/src/Base/PODVector.cpp#L79-L87

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very hard to reproduce locally... also cannot spot anything in valgrind yet.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems to be fixed by BLAST-ImpactX/impactx#1156 o.0

ret = np.array(tmp, copy=False)
assert ret.base is tmp
return ret
else:
return np.array(self, copy=False)
else:
Expand Down
Loading