Skip to content

Commit 2883631

Browse files
committed
feat: Computing Elements use MaxRAM
1 parent dde87cb commit 2883631

6 files changed

Lines changed: 36 additions & 10 deletions

File tree

src/DIRAC/Core/Utilities/CGroups2.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ def systemCall(self, *args, **kwargs):
300300
if "ceParameters" in kwargs:
301301
if cpuLimit := kwargs["ceParameters"].get("CPULimit", None):
302302
cores = float(cpuLimit)
303+
# MemoryLimitMB should be the job upper limit
303304
if memoryMB := int(kwargs["ceParameters"].get("MemoryLimitMB", 0)):
304305
memory = memoryMB * 1024 * 1024
305306
if kwargs["ceParameters"].get("MemoryNoSwap", "no").lower() in ("yes", "true"):

src/DIRAC/Interfaces/API/Job.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,18 +522,26 @@ def setDestination(self, destination):
522522
return S_OK()
523523

524524
#############################################################################
525-
def setRAMRequirements(self, ramRequired: int = 0):
525+
def setRAMRequirements(self, ramRequired: int = 0, maxRAMRequested: int = 0):
526526
"""Helper function.
527527
Specify the RAM requirements for the job in GB. 0 (default) means no specific requirements.
528528
"""
529529
if ramRequired:
530530
self._addParameter(
531531
self.workflow,
532-
"MaxRAM",
532+
"MinRAM",
533533
"JDL",
534534
ramRequired,
535535
"GBs of RAM requested",
536536
)
537+
if maxRAMRequested:
538+
self._addParameter(
539+
self.workflow,
540+
"MaxRAM",
541+
"JDL",
542+
maxRAMRequested,
543+
"GBs of RAM requested (Max to be used)",
544+
)
537545

538546
def setNumberOfProcessors(self, numberOfProcessors=None, minNumberOfProcessors=None, maxNumberOfProcessors=None):
539547
"""Helper function.

src/DIRAC/Resources/Computing/ComputingElement.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,14 @@ def setParameters(self, ceOptions):
236236
generalCEDict.update(self.ceParameters)
237237
self.ceParameters = generalCEDict
238238

239-
# If NumberOfProcessors/GPUs/RAM is present in the description but is equal to zero
239+
# If NumberOfProcessors/GPUs/MaxRAM is present in the description but is equal to zero
240240
# interpret it as needing local evaluation
241241
if self.ceParameters.get("NumberOfProcessors", -1) == 0:
242242
self.ceParameters["NumberOfProcessors"] = getNumberOfProcessors()
243243
if self.ceParameters.get("NumberOfGPUs", -1) == 0:
244244
self.ceParameters["NumberOfGPUs"] = getNumberOfGPUs()
245-
if self.ceParameters.get("RAM", -1) == 0:
246-
self.ceParameters["RAM"] = getAvailableRAM()
245+
if self.ceParameters.get("MaxRAM", 0) == 0:
246+
self.ceParameters["MaxRAM"] = getAvailableRAM()
247247

248248
for key in ceOptions:
249249
if key in INTEGER_PARAMETERS:

src/DIRAC/Resources/Computing/InProcessComputingElement.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def __init__(self, ceUniqueID):
2222
self.runningJobs = 0
2323

2424
self.processors = int(self.ceParameters.get("NumberOfProcessors", 1))
25+
self.maxRAM = int(self.ceParameters.get(["maxRAM"], 0))
2526
self.ceParameters["MaxTotalJobs"] = 1
2627

2728
def submitJob(self, executableFile, proxy=None, inputs=None, **kwargs):
@@ -118,4 +119,6 @@ def getCEStatus(self):
118119
result["WaitingJobs"] = 0
119120
# processors
120121
result["AvailableProcessors"] = self.processors
122+
# RAM
123+
result["MaxRAM"] = self.maxRAM
121124
return result

src/DIRAC/Resources/Computing/PoolComputingElement.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ def __init__(self, ceUniqueID):
6161
self.taskID = 0
6262
self.processorsPerTask = {}
6363
self.userNumberPerTask = {}
64-
self.ram = 1024 # Default RAM in GB (this is an arbitrary large value in case of no limit)
64+
self.ram = (
65+
1024 # Available RAM for the node, in GB. The default value is an arbitrary large value in case of no limit
66+
)
6567
self.ramPerTask = {}
6668

6769
# This CE will effectively submit to another "Inner"CE
@@ -77,9 +79,8 @@ def _reset(self):
7779
self.processors = int(self.ceParameters.get("NumberOfProcessors", self.processors))
7880
self.ceParameters["MaxTotalJobs"] = self.processors
7981
max_ram = int(self.ceParameters.get("MaxRAM", 0))
80-
if max_ram > 0:
81-
self.ram = max_ram // 1024 # Convert from MB to GB
82-
self.ceParameters["MaxRAM"] = self.ram
82+
if max_ram:
83+
self.ram = self.ceParameters["MaxRAM"]
8384
# Indicates that the submission is done asynchronously
8485
# The result is not immediately available
8586
self.ceParameters["AsyncSubmission"] = True
@@ -190,14 +191,18 @@ def _getMemoryForJobs(self, kwargs):
190191
"""
191192

192193
# # job requirements
193-
requestedMemory = kwargs.get("MaxRAM", 0)
194+
requestedMemory = kwargs.get("MinRAM", 0)
194195

195196
# # now check what the slot can provide
196197
# Do we have enough memory?
197198
availableMemory = self.ram - sum(self.ramPerTask.values())
198199
if availableMemory < requestedMemory:
199200
return None
200201

202+
# If there's a maximum amount of RAM allowed for the job, use that as maximum,
203+
if "MaxRAM" in kwargs and kwargs["MaxRAM"]:
204+
requestedMemory = int(kwargs["MaxRAM"])
205+
201206
return requestedMemory
202207

203208
def finalizeJob(self, taskID, future):

src/DIRAC/Resources/Computing/SingularityComputingElement.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def __init__(self, ceUniqueID):
115115
self.__installDIRACInContainer = False
116116

117117
self.processors = int(self.ceParameters.get("NumberOfProcessors", 1))
118+
self.maxRAM = int(self.ceParameters.get("MaxRAM", 0))
118119

119120
@staticmethod
120121
def __findInstallBaseDir():
@@ -413,6 +414,12 @@ def submitJob(self, executableFile, proxy=None, **kwargs):
413414

414415
self.log.debug(f"Execute singularity command: {cmd}")
415416
self.log.debug(f"Execute singularity env: {self.__getEnv()}")
417+
# systemCall below uses ceParameters["MemoryLimitMB"] as CG2 upper memory limit
418+
# if there's a max RAM available to the job, use that
419+
if self.maxRAM:
420+
self.ceParameters["MemoryLimitMB"] = min(
421+
self.maxRAM * 1024, self.ceParameters.get("MemoryLimitMB", 1024 * 1024)
422+
) # 1024 * 1024 is an arbitrary large number
416423
result = CG2Manager().systemCall(
417424
0, cmd, callbackFunction=self.sendOutput, env=self.__getEnv(), ceParameters=self.ceParameters
418425
)
@@ -449,4 +456,6 @@ def getCEStatus(self):
449456
result["WaitingJobs"] = 0
450457
# processors
451458
result["AvailableProcessors"] = self.processors
459+
# RAM
460+
result["MaxRAM"] = self.maxRAM
452461
return result

0 commit comments

Comments
 (0)