Skip to content

Commit 2afaa22

Browse files
authored
Improving calculation for total job memory (#2018)
1 parent f5dcc1d commit 2afaa22

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

armi/bookkeeping/memoryProfiler.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
https://pythonhosted.org/psutil/
3737
https://docs.python.org/3/library/gc.html#gc.garbage
3838
"""
39-
from math import floor
4039
from os import cpu_count
4140
from typing import Optional
4241
import gc
@@ -71,14 +70,11 @@ def describeInterfaces(cs):
7170
return (MemoryProfiler, {})
7271

7372

74-
def getTotalJobMemory(nTasksPerNode):
73+
def getTotalJobMemory(nTasks, cpusPerTask):
7574
"""Function to calculate the total memory of a job. This is a constant during a simulation."""
7675
cpuPerNode = cpu_count()
7776
ramPerCpuGB = psutil.virtual_memory().total / (1024**3) / cpuPerNode
78-
if nTasksPerNode == 0:
79-
nTasksPerNode = cpuPerNode
80-
cpusPerTask = floor(cpuPerNode / nTasksPerNode)
81-
jobMem = nTasksPerNode * cpusPerTask * ramPerCpuGB
77+
jobMem = nTasks * cpusPerTask * ramPerCpuGB
8278
return jobMem
8379

8480

@@ -137,14 +133,15 @@ def interactEOL(self):
137133
def printCurrentMemoryState(self):
138134
"""Print the current memory footprint and available memory."""
139135
try:
140-
nTasksPerNode = self.cs["nTasksPerNode"]
136+
cpusPerTask = self.cs["cpusPerTask"]
141137
except NonexistentSetting:
142138
runLog.extra(
143139
"To view memory consumed, remaining available, and total allocated for a case, "
144-
"add the setting 'nTasksPerNode' to your application."
140+
"add the setting 'cpusPerTask' to your application."
145141
)
146142
return
147-
totalMemoryInGB = getTotalJobMemory(nTasksPerNode)
143+
nTasks = self.cs["nTasks"]
144+
totalMemoryInGB = getTotalJobMemory(nTasks, cpusPerTask)
148145
currentMemoryUsageInGB = getCurrentMemoryUsage() / 1024
149146
availableMemoryInGB = totalMemoryInGB - currentMemoryUsageInGB
150147
runLog.info(

armi/bookkeeping/tests/test_memoryProfiler.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,18 @@ def test_getTotalJobMemory(self, mockCpuCount, mockVMem):
139139
vMem.total = (1024**3) * 50
140140
mockVMem.return_value = vMem
141141

142-
expectedArrangement = {0: 50, 1: 50, 2: 50, 3: 45, 4: 40, 5: 50}
143-
for nTasksPerNode, jobMemory in expectedArrangement.items():
144-
self.assertEqual(getTotalJobMemory(nTasksPerNode), jobMemory)
142+
expectedArrangement = {
143+
(10, 1): 50,
144+
(1, 10): 50,
145+
(2, 5): 50,
146+
(3, 3): 45,
147+
(4, 1): 20,
148+
(2, 4): 40,
149+
(5, 2): 50,
150+
}
151+
for compReq, jobMemory in expectedArrangement.items():
152+
# compReq[0] is nTasks and compReq[1] is cpusPerTask
153+
self.assertEqual(getTotalJobMemory(compReq[0], compReq[1]), jobMemory)
145154

146155
@patch("armi.bookkeeping.memoryProfiler.PrintSystemMemoryUsageAction")
147156
@patch("armi.bookkeeping.memoryProfiler.SystemAndProcessMemoryUsage")
@@ -166,20 +175,26 @@ def test_printCurrentMemoryState(
166175
mockVMem.return_value = vMem
167176
self._setMemUseMock(mockPrintSysMemUseAction)
168177
with mockRunLogs.BufferLog() as mockLogs:
169-
csMock = MagicMock()
170-
csMock.__getitem__.return_value = 2
171-
self.memPro.cs = csMock
178+
self.memPro.cs = {"cpusPerTask": 1, "nTasks": 10}
172179
self.memPro.printCurrentMemoryState()
173180
stdOut = mockLogs.getStdout()
174181
self.assertIn("Currently using 6.0 GB of memory.", stdOut)
175182
self.assertIn("There is 44.0 GB of memory left.", stdOut)
176183
self.assertIn("There is a total allocation of 50.0 GB", stdOut)
184+
# Try another for funzies where we only use half the available resources on the node
185+
mockLogs.emptyStdout()
186+
self.memPro.cs = {"cpusPerTask": 5, "nTasks": 1}
187+
self.memPro.printCurrentMemoryState()
188+
stdOut = mockLogs.getStdout()
189+
self.assertIn("Currently using 6.0 GB of memory.", stdOut)
190+
self.assertIn("There is 19.0 GB of memory left.", stdOut)
191+
self.assertIn("There is a total allocation of 25.0 GB", stdOut)
177192

178193
def test_printCurrentMemoryState_noSetting(self):
179194
"""Test that the try/except works as it should."""
180195
expectedStr = (
181196
"To view memory consumed, remaining available, and total allocated for a case, "
182-
"add the setting 'nTasksPerNode' to your application."
197+
"add the setting 'cpusPerTask' to your application."
183198
)
184199
with mockRunLogs.BufferLog() as mockLogs:
185200
self.memPro.printCurrentMemoryState()

0 commit comments

Comments
 (0)