-
Notifications
You must be signed in to change notification settings - Fork 113
[WIP] Libnethack shared #140
base: main
Are you sure you want to change the base?
Conversation
nle/nethack/nethack.py
Outdated
dlpath = os.path.join(self._vardir, "libnethack.so") | ||
shutil.copyfile(DLPATH, dlpath) | ||
# Create a HACKDIR for us. | ||
if os.getenv("SLURM_JOBID"): |
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 slurm stuff probably doesn't belong here and I'll most likely remove it from this PR
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'm not sure I can review this more than superficially.
Would be interested if this releves any lock contention issue the dlopen
/dlclose
cycles produced?
nle/nethack/nethack.py
Outdated
os.close(os.open(os.path.join(self._vardir, fn), os.O_CREAT)) | ||
os.mkdir(os.path.join(self._vardir, "save")) | ||
if _pynethack.supports_shared(): | ||
# "shared" mode does some hacky things to enable using a |
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 mix of 2-letter and 4-letter indentation is weeeiiiirdd
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, it is. I apologize. I come from a world of 2 indentation. Formatting will be cleaned up.
sys/unix/nleshared.cc
Outdated
endaddr = 0; | ||
size = 0; | ||
|
||
forPh([&](Elf64_Phdr* ph) {; |
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 have a very vague notion of what this is doing: It's like a reimplementation of parts of Linux dynamic library loading. It interprets the data in the so in ELF format, creates manual copies ("forks"), and gives access to symbols a la dlsym
.
I can't claim I understand much beyond that and perhaps a few comments might be good?
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 will try to outline the behavior in comments.
nle/nethack/nethack.py
Outdated
@@ -75,13 +75,13 @@ def _set_env_vars(options, hackdir, wizkit=None): | |||
if wizkit is not None: | |||
os.environ["WIZKIT"] = wizkit | |||
|
|||
_nhinstances = 0 | |||
|
|||
# TODO: Not thread-safe for many reasons. | |||
# TODO: On Linux, we could use dlmopen to use different linker namespaces, |
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.
We can probably update some of these comments when we merge this.
Ah I read the PR description now.
If you make them call As for the not-writing any files approach: I'm not sure to what extend users are currently using the built-in highscore (written to a file, persistent for one instance of NLE). Probably not much, and very probably not enough to warrant doing something different than you are doing here. If only there were a POSIX way of doing this :P |
Great, thanks. The records (highscore) file could be made persistent between resets, but is there even anything it could be used for?
The other approach to replacing these functions would of course be to do it in nethack, through the system specific configs and defines. |
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.
One more question:
It will be possible to track memory resources to detect leaks or force cleanup.
How would you do that? Overriding each of malloc
, alloc
, posix_memalign
, etc?
It's not very important; the only effect a persistent highscore has is that the replays contain this relative comparison of the episode that just ended with other episodes. I'm not sure to what extend researchers look at replays and the highscore data in there. |
sys/unix/nleshared.cc
Outdated
size_t baseaddr = ~0; | ||
size_t endaddr = 0; | ||
|
||
forPh([&](Elf64_Phdr* ph) { |
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'm assuming this is fast enough to not need the ability to break
based on e.g. a return value of the lambda?
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 code only runs once in the entire lifespan of the process, so... There's really nothing to be gained by making this stuff faster.
(also, it is very fast yeah)
I'm creating this draft PR as things appear to be fully functional, but there are at minimum some cleanups necessary, and some more functionality I'd like to add.
This introduces a "shared" mode to the libnethack approach. It is Linux-only, and implements manual loading of the shared object file to avoid the need to copy the library anywhere and to better isolate the environment.
It is enabled by default on Linux and will fall back to the existing (dlopen) behavior on other platforms.
I called it shared as the shared object is actually shared between instances. Yey.
Some advantages: