-
Notifications
You must be signed in to change notification settings - Fork 20
Adapt arch target map #312
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
Conversation
…e keys don't have meaning, and all meaning is in the values
…so, make sure to print the same information to the logs, regardless of whether this is about a partition that has accelerators defined or not. Finally, make sure that if we have not hit a match by the end of the loop over all accelerators, we continue to the next iteration of the loop over the repo-targets, so that the job-dir preparation is skipped for the current one
…AND if the build command does NOT, we explicitely check that the defined accelerator is 'None'. This allows skipping CPU-only builds on accelerated partitions.
…, as it is now replaced by the repo list in the arch_target_map. Also, fix hound issues
…o individual partitions when printing the config
trz42
left a comment
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.
Left a bunch of comments.
This PR does actually more than what was originally "requested" in #294
It provides more control for bot admins to allow/prevent certain jobs to be triggered, e.g., one might prevent accidental CPU-only builds on GPU-nodes. This feature is welcome, I think, although it changes the meaning of the accelerator filter. I don't know if the "prevent GPU builds on CPU-only nodes" is really necessary though. Main problem could be that is not so clear why some filter trigger a build and some other not.
While I'll have to give this a test run, I believe it does what it should do.
The move (or removal) of the repo_target_map is not necessary (I think, but I may be wrong). It doesn't hurt either.
I wonder if one should simply rename arch_target_map to make a braking change...
Also for the bot command filter names, I wonder if one could do better, e.g.,
| current | new | comment |
|---|---|---|
architecture |
node or node_type ... |
arch_target_map could be renamed to node_map or node_type_map |
... cpu |
this would allow to make the definition of node types or partitions simpler OR use the information for verifying (similar to what is done for accel) |
I wonder if we really need to have os and cpu_subdir in the definition of a partition, and use them to set the architecture (in the context when matching filters). Maybe it would be better to add another filter for cpu (defines for what CPU microarchitecture we want to build for). os and cpu_subdir are really odd things that should not matter much to the bot. They should be just passed through to the job.
Similarly, do we really care about the repository information when we want to trigger a job on a zen4 node? It may add some options for an admin to constrain certain combinations ... however it feels a bit odd that this is a bot configuration option.
app.cfg.example
Outdated
|
|
||
|
|
||
| [architecturetargets] | ||
| # defines for which architectures the bot will build and what job submission |
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.
| # defines for which architectures the bot will build and what job submission | |
| # defines for which architectures (CPU and/or GPU) the bot can build and what job submission |
app.cfg.example
Outdated
| [architecturetargets] | ||
| # defines for which architectures the bot will build and what job submission | ||
| # parameters shall be used to allocate a compute node with the correct | ||
| # parameters shall be used to allocate a compute node with the correct |
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.
| # parameters shall be used to allocate a compute node with the correct | |
| # parameters shall be used to allocate a compute node with the correct CPU(+GPU) architecture |
app.cfg.example
Outdated
| # defines for which architectures the bot will build and what job submission | ||
| # parameters shall be used to allocate a compute node with the correct | ||
| # parameters shall be used to allocate a compute node with the correct | ||
| # The keys of the arch_target_map are virtual partition names. They don't have any meaning in the bot code, |
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 keys of the arch_target_map are virtual partition names. They don't have any meaning in the bot code, | |
| # The keys of the arch_target_map are just strings. They don't have any meaning in the bot code, |
"virtual" and "partition" carry some meaning which could be misleading.
app.cfg.example
Outdated
| # parameters shall be used to allocate a compute node with the correct | ||
| # parameters shall be used to allocate a compute node with the correct | ||
| # The keys of the arch_target_map are virtual partition names. They don't have any meaning in the bot code, | ||
| # and can thus be chosen as desired. |
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.
| # and can thus be chosen as desired. | |
| # and can thus be chosen as desired (however, they could be standardised across different bot instances run by an organisation, so users easily understand what they mean). |
app.cfg.example
Outdated
| # parameters shall be used to allocate a compute node with the correct | ||
| # The keys of the arch_target_map are virtual partition names. They don't have any meaning in the bot code, | ||
| # and can thus be chosen as desired. | ||
| # Note that you are responsible that ANY bot:build command ONLY matches a single virtual partition! |
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.
As of now this is the case, but with #310 which only supports exact matches this wouldn't be an issue any longer.
| # Note that you are responsible that ANY bot:build command ONLY matches a single virtual partition! | |
| # Note that you are responsible that ANY bot:build command ONLY matches a single key for the architecture! |
Actually, this is a little off. Maybe it would be better to explain that (without #310) if one has defined the keys zen4 and zen4+H100, then a bot:build arch:zen4 would result in two jobs. So, at the moment, none of the keys should be a substring of another key.
app.cfg.example
Outdated
| # the event_filter will NOT mark this virtual partition as a valid match. This is intentional, as this particular | ||
| # (example) cluster has a native zen4+cc90 partition (gpu_h100) and we want this command to trigger a native build | ||
| # on that partition, rather than cross-compiling on this cpu_zen4 partition. |
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.
Is that really the intention? It changes the meaning of accel as we used it until now (defining for which accelerator we want to build for) to if zen4 architecture target defines "accel": ["None"] it is interpreted as a means to select or not select a build node. If cpu_zen4 architecture target does not define "accel" it is interpreted as a means to define for which accelerator we want to build for).
Plus the selection of the build node is now sometimes the result of only arch and sometimes the result of both arch and accel?
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's always been a bit strange to me why accel had a different meaning than arch. I.e. arch was used for node selection, but accel wasn't. The only reason that 'worked' was because we always do native builds, and arch thus actually meant both: give me a node that matches this architecture and build for this architecture (i.e. in this architectures prefix). Somehow, accel was special in that it did not have any effect on node selection. But it has to if we ever want to enable a combination of native and cross-compiled builds (how else do I ensure a native build?).
Anyway, I think this:
if zen4 architecture target defines "accel": ["None"] it is interpreted as a means to select or not select a build node. If cpu_zen4 architecture target does not define "accel" it is interpreted as a means to define for which accelerator we want to build for).
Should be seen differently. If a partition defines "accel": ["None"] that is a declaration that this partition is not suitable for (/should not be used for) compiling for accelerators. If a partition does not define "accel", that is an (implicit) declaration that it may be used to (cross)-compile for any accelerator.
The build command then defines what accelerator we want to build for (e.g. it determines the prefix in which we'll install software). It is the job of the matching logic to then select a partition that can facilitate that request.
This is pretty equivalent to how ReFrame does things with partition features. A ReFrame config can declare "Partition A has a feature 'GPU', Partition B does not". A test can declare "I need a partition with the feature 'GPU' to run". As a result, when running ReFrame on a system with Partition A and B, that test will then only be scheduled on Partition A.
eessi_bot_event_handler.py
Outdated
| # Do not print virtual partition names, a bot admin may not want to share those | ||
| # Instead, just number them | ||
| comment += f"\n- Partition {partition_num+1}:" |
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.
How would one be able to know the names if they are not shown?
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 don't need to know. They could be named foo and bar, it's not relevant to the end user, since the names don't have any meaning (it's just helpful for the bot admin to pick a 'sensible' name :))
tasks/build.py
Outdated
| # for a lot of accelerator targets | ||
| # arch_target_map = { | ||
| # 'virtual_partition_name': { | ||
| # 'os': 'linux', | ||
| # 'cpu_subdir': 'x86_64/amd/zen4', | ||
| # 'accel': ['nvidia/cc90'], | ||
| # 'slurm_params': '-p genoa <etc>', | ||
| # 'repo_targets': ["eessi.io-2023.06-compat","eessi.io-2023.06-software"], | ||
| # }, | ||
| # 'virtual_partition_name2': { | ||
| # ... etc |
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 could be used at the start of the explanation in app.cfg.example.
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.
Good point, I'll move it.
tasks/build.py
Outdated
| if 'accel' in partition_info and accelerator is not None: | ||
| # Use the accelerator as defined by the action_filter. We check if this is valid for the current | ||
| # virtual partition later | ||
| arch_dir += accelerator |
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.
arch_dir could become x86_64/amd/zen4nvidia/cc90 ?
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 mean: the slash after zen4 is missing? That's indeed a mistake
app.cfg.example
Outdated
| # "accel": ["nvidia/cc70", "nvidia/cc80", "nvidia/cc90"] | ||
| # Note that setting: | ||
| # "accel": ["None", "nvidia/cc90"] | ||
| # is invalid here, since it would lead to both the cpu_zen4 and the gpu_h100 partitions matching the build command |
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.
"Invalid" in the sense the bot checks and refuses to even start or "invalid" in the sense it is not recommended because it's ambiguous?
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.
Invalid in the sense it will lead to an error (the bot will fail on prepare the job dir for the gpu_h100 partition because that job dir was already prepared for the same job on cpu_zen4).
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.
Which would never happen if partitions have unique names and a user targets a partition by its name. Would also be easier to understand what is going on.
|
There's actually one thing that may unnecessarily limit what we could achieve here. With the For example, but this would require a departure from the current filters ( This could be particularly useful when submitting jobs to busy HPC clusters. However, it also feels like using the same hammer for another problem -- tweaking submission parameters -- maybe that would be better supported with another filter |
You don't have to prevent GPU builds on CPU only nodes. But we need the possibility to do this, because otherwise, two partitions match, and the bot will try to prep the job twice in the same builddir. See this issue The alternative way of fixing this issue is to break the loop after the first match. But in that case the order of partitions in the |
Removing it keeps things clean - it is no longer used, as far as I could tell. But I do like your idea of renaming |
Hm, yeah, I'm not sure if 'the same hammer' is the solution here. Unless you consider 'max walltime' a requirement for the build job (just like a particular architecture or accelerator is). Then you could say, the person commanding the bot declares what they need, and they get a partition that has a max walltime that is at least the amount they requested. Then, it would just be another filter option, essentially. And, we'd have to make that timelimit a separate field in the config (just like "os" and "cpu_subdir" are currently) so that it can easily be compared against. Finally, it would require then adding a But indeed, a submitopts:arg=value may be a better approach here. Whatever we choose, I'd do that in a follow-up PR, I see no reason to combine it with the current one. |
To me this sounds the concept is not right if we need extra configuration to prevent something.
Strange argument. The current code uses the key "OS/CPU_ARCH" for defining part of the installation directory. That needs to be changed. |
|
Discussed some things with Thomas on chat, some conclusions: The real issue may not have been that keys have meaning, but that the The proposed solution is to split the two concerns by making two separate bot arguments, e.g.:
or
The bot config could then be: Some questions that were still open in the discussion:
The suggestion by @trz42 was to add Note that this doesn't handle the second question. What if a bot config has and a builder does:
With the requirement that all elements of the context should be present as filter, I don't see how a filter could match multiple partitions - the above config doesn't really make sense, as there wouldn't be any bot:build command that only matches the second node type. So, maybe option 2 is the most sensible: maybe we should just print an informative error stating that the bot config is invalid, because there is no (functional) distinction between The final thing that was discussed is that it may be good to give the ability to select a partition directly, without filter matching. I.e. |
|
Just a note: the |
|
TODO's:
Won't do:
|
|
Reporting of which arch it builds for: casparvl/software-layer#1 (comment) |
…th multiple types of accelerators in a single node can be configured as two separate node types if needed
bedroge
left a comment
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.
Part 1 😉
Clarify descriptions in app.cfg.example Co-authored-by: Bob Dröge <b.e.droge@rug.nl>
bedroge
left a comment
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.
Review part 2 (build.py
| on_arch = '-'.join(job.arch_target.split('/')[1:]) | ||
|
|
||
| # Obtain the architecture to build for | ||
| for_arch = build_params[BUILD_PARAM_ARCH] |
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 started wondering here if build_params shouldn't be part of the job namedtuple, since they both contain information about the build job?
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 build parameters (i.e. anything passed to for: on the command line) need to somehow make their way from the bot_command as it is present in handle_bot_command_build to this point (and to the prepare_jobs() function as well, where it is also needed). Short of passing the raw bot_command in it's entirety, the best way to do this is to create a separate data structure for it.
Note that create_pr_comment indeed receives both job and build_params. But prepare_jobs() doesn't: instances of the jobs NamedTuple only get create in that function. Thus, the only way to get things from handle_bot_command_build to prepare_jobs() is to pack them in a data structure, and pass them as arguments through the respective functions.
The only alternative I see is passing the full bot_command down to prepare_jobs, but I would consider that bad practice, as it creates less isolated code by passing more information than is required.
…his option is no longe rused
…docstring for status command to show the correct return type (string)
…ted on the docstring and comments of the template_to_regex function, since it's functionality may be a bit hard (abstract) to understand otherwise.
Co-authored-by: Bob Dröge <b.e.droge@rug.nl>
Co-authored-by: Bob Dröge <b.e.droge@rug.nl>
|
Tested in SURF-hpcv/software-layer-scripts#2. |
|
@casparvl The README file still explains how to use (I would've preferred a more gradual transition, like keeping support for |
I considered this, but it would have been quite complex to keep both (and the PR was already quite complex). Considering we've made plenty of breaking changes to the config before, I consider mine to be reasonably 'nice' since the bot will inform you upon startup that you have a key defined in your config which is no longer supported, and by what it got replaced... So even if you didn't know about this PR, you would have been pointed in the right direction :) I'll fix the README though, good point |
This PR restructures the
arch_target_mapconfiguration item (and any place in the code that used it), so that the keys no longer have meaning. This allows having e.g. a CPU partition based onzen4and an accelerated partition based onzen4, but have the bot distinguish between them. This then allows the user to target the CPU or GPU partition, based on what is desired for the build.The functionality implemented here enables:
It should thus be flexible enough to create a configuration that 'makes sense' on any system. As an example: Snellius has both
zen4CPU-only nodes, andzen4+H100nodes. This PR allows me to configure the bot in such a way that e.g. CPU-onlyzen4builds, as well aszen4 + nvidia/cc70andzen4 + nvidia/cc80builds are done on the CPU-only partition withzen4nodes, while thezen4 + nvidia/cc90builds will use the GPU partition (zen4 + H100 nodes) so that they can build that GPU software natively.The
repo_target_mapis no longer needed, as each virtual partition in thearch_target_mapnow declares itself for which repositories it is configured to build. This also allows some extra flexibility, as one could e.g. allow building for theeessi.io-2023.06-compatonly on CPU-only nodes. Not sure if this is super useful, but the flexibility comes for free with the new structure.Finally, all the places in the code that used
repo_target_maphave been rewritten. As far as I could tell, that was mainly thehandle_pull_request_opened_eventfunction.Fixes: #294