-
Notifications
You must be signed in to change notification settings - Fork 623
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
Option to limit process requirements instead of exiting with error #640
Comments
As well as / instead of these manually specified limits, there could perhaps be something similar to process {
notEnoughResources: 'terminate' // default behaviour
notEnoughResources: 'limit' // throttle to available resources
notEnoughResources: { // limit to specified values
cpus: 4
memory: 8.GB
time: 16.h
}
} |
So, as first thing I would suggest to use this simplified version of
Still not sure if the best thing is to add a build-in function like the above or implement a move advanced feature as you are suggesting in the second comment. |
Ace! Thanks for the improved function, I will use that in the short term at least 👍 Still think that the core feature would be better though 😉 |
also the
I agree ! |
Aha, because we're now testing the type - nice! But if supplied on the command line, will these not always be strings? I think that's why I was trying to coerce the type (and catching the exception if it failed).. |
I was a bit too optimistic, yes the |
Could probably just have one |
Yep, but want be able anymore to have specific error message then |
You could check the type of |
lol |
I can't resist a challenge 😆How about this? def check_max(obj, max) {
def obj_types = [
'memory': nextflow.util.MemoryUnit,
'time': nextflow.util.Duration,
'cpus': Integer
]
obj_types.each { key, obj_type ->
try {
if( obj instanceof obj_type )
return obj.compareTo(max as obj_type) == 1 ? max as obj_type : obj
catch( all ) {
println " ### ERROR ### Max $key '${max}' is not valid! Using default value: $obj"
return obj
}
}
println " ### ERROR ### Object type not recognised! Using default value: $obj"
return obj
} |
if it works, it's good :) |
Haven't tested it yet.. ;) Copying my main request back down here as we got a bit carried away by function refactoring 😁 process {
notEnoughResources: 'terminate' // default behaviour
notEnoughResources: 'limit' // throttle to available resources
notEnoughResources: { // limit to specified values
cpus: 4
memory: 8.GB
time: 16.h
}
} |
I was thinking at this, however I'm not understanding how resource are modified? Do you still need to provide a dynamic (ie closure) rule to increase the request when the task re-submitted or you were thinking to something different ? |
Not sure I totally understand the question. But I was thinking that the syntax could remain the same as it is currently - static values would be limited (modified) at runtime by nextflow if needed to make them smaller, dynamic rules could be used with |
I mean, basically your proposal is to provide a mechanism that allows the setting of a max limits for some resources. Whenever the resource request overcome this limit (either statically or dynamically defined), it fallback to this limit. Is that right? |
Yup! |
Proposed syntax after discussion with default value and also a range (minimum and maximum values). process {
withName:fastqc {
memory: { 1.GB * input.size(), range: 8.GB..24.GB },
time: { 2.4.h * input.size(), range: 16.h..48.h },
cpus: { 2 * input.size(), range: 4..16 }
}
} The Another scenario is when people want to limit the requested resources: process {
memory: 4.GB
withName:fastqc {
memory: 16.GB, range: 8.GB..24.GB
}
withName:star {
memory: 4.GB, range: 2.GB..6.GB
}
} Then have However, doing Phil |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This is still probably my number-1 feature request issue 😄 The @nf-core |
I agree we need definitively better here, soon I need to tackle this problem. Pinning this issue. |
Are the additional attributes (sorry I forget the name in Groovy) inherited separately to the main value? For example, would my process 'foo' here also have a max of process.memory = 3.GB, max: 10.GB
process.withName['foo'].memory = 20.GB |
I don't plan to implement that kind of behavior at the moment. Are there any other directives that can inherit individual attributes like that? For example I don't think |
Not that I know of. Would it be acceptable to use a distinct namespace instead to be able to achieve this? eg. Something along the lines of my original suggestion way up there 👆🏻 process {
notEnoughResources: 'terminate' // default behaviour
notEnoughResources: 'limit' // throttle to available resources
notEnoughResources: { // limit to specified values
cpus: 4
memory: 8.GB
time: 16.h
}
} Then it can be defined once to work across an entire workflow (desired behaviour 99% of the time I suspect) but also at process level if more granular control is needed. |
I like this idea. No need to refactor the resource directives, Nextflow just needs to apply these limits before submitting a task. I would make it even simpler:
|
Yeah I think the So I'm fully behind your suggested syntax 👍🏻 (was |
This is interesting, but I don't fully understand the semantics of this. Is it meant to throttle the resources on retry? |
Yes. If you specify the resource limits, Nextflow will throttle any resource requests that exceed the limits. If you don't specify a limit, then such a request would fail. However it just occurred to me that on some systems, an unschedulable task will just sit in the queue forever, so we might want a way to specify whether Nextflow should throttle or fail, like the example Phil gave. |
Hi, Would below code in a config file work currently as an alternative to defining a
Best, |
That should work. I believe |
@bentsherman If I'm understanding correctly #2911 does not implement any throttling, and it's a mere config attribute that should be managed by the user via a dynamic rule (closure). Is that correct? |
It does throttle the task resources, see |
Maybe we are using throttling with different meaning. Stating the docs
I understand this as constraint mechanism. Instead I was expecting throttling as mechanism so increase automatically the resource depending the retry |
It is a constraint mechanism. You could also see it as throttling, though a different form than what you are talking about |
What is preventing to add a third parameter to the Nextflow should aim instead to provide a built-in replacement for the |
That's what this issue and PR #2911 is about.. I'd like to remove that config function entirely if possible. |
Not really, #2911 adds a directive to allow the specify the upper bound, |
Paolo I think you are misunderstanding. #2911 adds a directive to replace |
Can you show me an example a process is expected to be written using #2911 to automatically increase the memory on a failure |
Just the normal dynamic resource pattern: process {
memory = { 8.GB * task.attempt }
resourceLimits = [
memory: 64.GB
]
} |
How the increment is determined? I don't see anything obvious in the PR |
The increment is independent of the resource limit. The example I just gave means "increase the task memory by 8 GB on each attempt until the system-wide limit of 64 GB is reached" |
Edit: Had an old browser tab and didn't see the more recent replies sorry. Wrote the below in response to this comment. Gotcha, sorry it took @bentsherman explaining your comment to me. I'd prefer a global level setting rather than continued use of the I don't think that there's ever a time when you don't want these limits applied, as they're there to prevent Nextflow from crashing due to unsatisfiable requests. There's also no time when you want the limits to vary on a process-level. They are there to meet computational environment limits so they don't vary by process. If you want to change that, you do it with the regular So because of this, to me it makes more sense to have a workflow-level setting vs. a function that can be used within multiple process-level directives. |
Basically instead of this: process {
withName:'MYPROCESS_1' {
memory = { check_max( 72.GB * task.attempt, 'memory' ) }
time = { check_max( 24.h * task.attempt, 'time' ) }
cpus = { check_max( 4 * task.attempt, 'cpus' ) }
}
withName:'MYPROCESS_2' {
memory = { check_max( 72.GB, 'memory' ) }
time = { check_max( 24.h, 'time' ) }
cpus = { check_max( 4, 'cpus' ) }
}
withName:'MYPROCESS_3' {
memory = { check_max( 72.GB * task.attempt, 'memory' ) }
time = { check_max( 24.h * task.attempt, 'time' ) }
cpus = { check_max( 4 * task.attempt, 'cpus' ) }
}
} I'd much rather have this: process {
resourceLimits = [ memory: 64.GB, time: 24.h, cpus: 12 ]
withName:'MYPROCESS_1' {
memory = { 72.GB * task.attempt }
time = { 24.h * task.attempt }
cpus = { 4 * task.attempt }
}
withName:'MYPROCESS_2' {
memory = 72.GB
time = 24.h
cpus = 4
}
withName:'MYPROCESS_3' {
memory = { 72.GB * task.attempt }
time = { 24.h * task.attempt }
cpus = { 4 * task.attempt }
}
} Especially as the |
If Nextflow encounters a process that requests resources that are not available on the current system, it fails. For example, if 10 processors are requested and the system only has 8, we exit with an error. This is A Good Thing 👍
However, when making config files for a pipeline that aim to have generic works-for-most-situations requests, it can be nice to be able to throttle these for small genomes / test datasets / small machines for example.
In most of our pipelines, we now have this little helper function in
nextflow.config
:Then, in each config we wrap the request in the above function, as so:
This way, the defaults work most of the time. But if you pass
--max_memory "8.GB"
then all processes will use a maximum of8.GB
and the pipeline will run on your tiny machine. This is really helpful for test datasets and allows us to have a default "base" config file that is throttled by other system-specific configs.Is this something that could be built into Nextflow as a new feature? Keep the current default behaviour, but have new command line arguments and config scopes to be able to throttle the maximum resources without failing..
Phil
The text was updated successfully, but these errors were encountered: