@@ -474,59 +474,49 @@ def set_gres_string(job: JobExecutorInterface) -> str:
474474 Function to set the gres string for the SLURM job
475475 based on the resources requested in the job.
476476 """
477- # generic resources (GRES) arguments can be of type
477+ # generic resources (GRES) arguments can be of type "string",
478478 # "string:int" or "string:string:int" with optional postfix 'T' or 'G' or 'M'
479- gres_re = re .compile (r"^[a-zA-Z0-9_]+(:[a-zA-Z0-9_\.]+)?:\d+[TGM]?$" )
479+ gres_re = re .compile (r"^[a-zA-Z0-9_]+(:[a-zA-Z0-9_\.]+)?( :\d+[TGM]?) ?$" )
480480
481481 # gpu model arguments can be of type "string"
482482 # The model string may contain a dot for variants, see
483483 # https://github.com/snakemake/snakemake-executor-plugin-slurm/issues/387
484484 gpu_model_re = re .compile (r"^[a-zA-Z0-9_\.]+$" )
485+
485486 # any arguments should not start and end with ticks or
486487 # quotation marks:
487488 string_check = re .compile (r"^[^'\"].*[^'\"]$" )
489+
488490 # The Snakemake resources can be only be of type "int",
489491 # hence no further regex is needed.
490492
491- gpu_string = None
492- if job .resources .get ("gpu" ):
493- gpu_string = str (job .resources .get ("gpu" ))
494-
495- gpu_model = None
496- if job .resources .get ("gpu_model" ):
497- gpu_model = job .resources .get ("gpu_model" )
498-
499- # ensure that gres is not set, if gpu and gpu_model are set
500- if job .resources .get ("gres" ) and gpu_string :
501- raise WorkflowError (
502- "GRES and GPU are set. Please only set one of them." , rule = job .rule
503- )
504- elif not job .resources .get ("gres" ) and not gpu_model and not gpu_string :
505- return ""
506-
493+ # GRES
494+ gres = ""
507495 if job .resources .get ("gres" ):
508496 # Validate GRES format (e.g., "gpu:1", "gpu:tesla:2")
509- gres = job .resources .gres
510- if not gres_re .match (gres ):
511- if not string_check .match (gres ):
497+ if not gres_re .match (job .resources .gres ):
498+ if not string_check .match (job .resources .gres ):
512499 raise WorkflowError (
513500 "GRES format should not be a nested string (start "
514501 "and end with ticks or quotation marks). "
515- "Expected format: "
502+ "Expected format: '<name>', "
516503 "'<name>:<number>' or '<name>:<type>:<number>' with an optional "
517504 "'T' 'M' or 'G' postfix "
518- "(e.g., 'gpu:1 ' or 'gpu:tesla:2 ')"
505+ "(e.g., 'gpu', 'gpu:2 ' or 'gpu:tesla:1 ')"
519506 )
520507 else :
521508 raise WorkflowError (
522- f"Invalid GRES format: { gres } . Expected format: "
523- "'<name>:<number>' or '<name>:<type>:<number>' with an optional "
524- "'T' 'M' or 'G' postfix "
525- "(e.g., 'gpu:1' or 'gpu:tesla:2') "
509+ f"Invalid GRES format: { job . resources . gres } . Expected format: "
510+ "'<name>', '<name> :<number>' or '<name>:<type>:<number>' "
511+ "with an optional 'T' 'M' or 'G' postfix "
512+ "(e.g., 'gpu', 'gpu :1' or 'gpu:tesla:2') "
526513 )
527- return f" --gres={ job .resources .gres } "
514+ gres += f" --gres={ job .resources .gres } "
528515
529- if gpu_model and gpu_string :
516+ # GPU
517+ gpu_string = job .resources .get ("gpu" )
518+ gpu_model = job .resources .get ("gpu_model" )
519+ if gpu_model :
530520 # validate GPU model format
531521 if not gpu_model_re .match (gpu_model ):
532522 if not string_check .match (gpu_model ):
@@ -540,10 +530,12 @@ def set_gres_string(job: JobExecutorInterface) -> str:
540530 f"Invalid GPU model format: { gpu_model } ."
541531 " Expected format: '<name>' (e.g., 'tesla')"
542532 )
543- return f" --gpus= { gpu_model } : { gpu_string } "
544- elif gpu_model and not gpu_string :
545- raise WorkflowError ( "GPU model is set, but no GPU number is given" )
533+ # Default GPU to 1
534+ gpu_string = job . resources . get ( "gpu" , "1" )
535+ gres += f" --gpus= { gpu_model } : { gpu_string } "
546536 elif gpu_string :
547537 # we assume here, that the validator ensures that the 'gpu_string'
548538 # is an integer
549- return f" --gpus={ gpu_string } "
539+ gres += f" --gpus={ gpu_string } "
540+
541+ return gres
0 commit comments