Skip to content
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

[core] Add cgroups support to meshroom #1836

Merged
merged 9 commits into from
Dec 8, 2022
101 changes: 101 additions & 0 deletions meshroom/core/cgroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env python
# coding:utf-8

import os

#Try to retrieve limits of memory for the current process' cgroup
def getCgroupMemorySize():

#first of all, get pid of process
pid = os.getpid()

#Get cgroup associated with pid
filename = f"/proc/{pid}/cgroup"

cgroup = None
try:
with open(filename, "r") as f :

#cgroup file is a ':' separated table
#lookup a line where the second field is "memory"
lines = f.readlines()
for line in lines:
tokens = line.rstrip("\r\n").split(":")
if len(tokens) < 3:
continue
if tokens[1] == "memory":
cgroup = tokens[2]
except OSError:
pass

if cgroup is None:
return -1

size = -1
filename = f"/sys/fs/cgroup/memory/{cgroup}/memory.limit_in_bytes"
try:
with open(filename, "r") as f :
value = f.read().rstrip("\r\n")
if value.isnumeric():
size = int(value)
except OSError:
pass

return size

def parseNumericList(numericListString):

nList = []
for item in numericListString.split(','):
if '-' in item:
start, end = item.split('-')
start = int(start)
end = int(end)
nList.extend(range(start, end + 1))
else:
value = int(item)
nList.append(value)

return nList

#Try to retrieve limits of cores for the current process' cgroup
def getCgroupCpuCount():

#first of all, get pid of process
pid = os.getpid()

#Get cgroup associated with pid
filename = f"/proc/{pid}/cgroup"

cgroup = None
try:
with open(filename, "r") as f :

#cgroup file is a ':' separated table
#lookup a line where the second field is "memory"
lines = f.readlines()
for line in lines:
tokens = line.rstrip("\r\n").split(":")
if len(tokens) < 3:
continue
if tokens[1] == "cpuset":
cgroup = tokens[2]
except OSError:
pass

if cgroup is None:
return -1

size = -1
filename = f"/sys/fs/cgroup/cpuset/{cgroup}/cpuset.cpus"
try:
with open(filename, "r") as f :
value = f.read().rstrip("\r\n")
nlist = parseNumericList(value)
size = len(nlist)

except OSError:
pass

return size

32 changes: 32 additions & 0 deletions meshroom/core/desc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from meshroom.common import BaseObject, Property, Variant, VariantList, JSValue
from meshroom.core import cgroup

from collections.abc import Iterable
from enum import Enum
Expand Down Expand Up @@ -534,16 +535,19 @@ class CommandLineNode(Node):
commandLineRange = ''

def buildCommandLine(self, chunk):

cmdPrefix = ''
# if rez available in env, we use it
if 'REZ_ENV' in os.environ and chunk.node.packageVersion:
# if the node package is already in the environment, we don't need a new dedicated rez environment
alreadyInEnv = os.environ.get('REZ_{}_VERSION'.format(chunk.node.packageName.upper()), "").startswith(chunk.node.packageVersion)
if not alreadyInEnv:
cmdPrefix = '{rez} {packageFullName} -- '.format(rez=os.environ.get('REZ_ENV'), packageFullName=chunk.node.packageFullName)

cmdSuffix = ''
if chunk.node.isParallelized and chunk.node.size > 1:
cmdSuffix = ' ' + self.commandLineRange.format(**chunk.range.toDict())

return cmdPrefix + chunk.node.nodeDesc.commandLine.format(**chunk.node._cmdVars) + cmdSuffix

def stopProcess(self, chunk):
Expand Down Expand Up @@ -589,6 +593,34 @@ def processChunk(self, chunk):
finally:
chunk.subprocess = None

#specific command line node for alicevision apps
class AVCommandLineNode(CommandLineNode):

cgroupParsed = False
cmdMem = ''
cmdCore = ''

def __init__(self):

if AVCommandLineNode.cgroupParsed is False:

AVCommandLineNode.cmdMem = ''
memSize = cgroup.getCgroupMemorySize()
if memSize > 0:
AVCommandLineNode.cmdMem = ' --maxMemory={memSize}'.format(memSize=memSize)

AVCommandLineNode.cmdCore = ''
coresCount = cgroup.getCgroupCpuCount()
if coresCount > 0:
AVCommandLineNode.cmdCore = ' --maxCores={coresCount}'.format(coresCount=coresCount)

AVCommandLineNode.cgroupParsed = True

def buildCommandLine(self, chunk):

commandLineString = super(AVCommandLineNode, self).buildCommandLine(chunk)

return commandLineString + AVCommandLineNode.cmdMem + AVCommandLineNode.cmdCore

# Test abstract node
class InitNode:
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/CameraCalibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class CameraCalibration(desc.CommandLineNode):
class CameraCalibration(desc.AVCommandLineNode):
commandLine = 'aliceVision_cameraCalibration {allParams}'

category = 'Utils'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/CameraInit.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def readSfMData(sfmFile):
return views, intrinsics


class CameraInit(desc.CommandLineNode, desc.InitNode):
class CameraInit(desc.AVCommandLineNode, desc.InitNode):
commandLine = 'aliceVision_cameraInit {allParams} --allowSingleView 1' # don't throw an error if there is only one image

size = desc.DynamicNodeSize('viewpoints')
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/CameraLocalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from meshroom.core import desc


class CameraLocalization(desc.CommandLineNode):
class CameraLocalization(desc.AVCommandLineNode):
commandLine = 'aliceVision_cameraLocalization {allParams}'

category = 'Utils'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/CameraRigCalibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from meshroom.core import desc


class CameraRigCalibration(desc.CommandLineNode):
class CameraRigCalibration(desc.AVCommandLineNode):
commandLine = 'aliceVision_rigCalibration {allParams}'

category = 'Utils'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/CameraRigLocalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from meshroom.core import desc


class CameraRigLocalization(desc.CommandLineNode):
class CameraRigLocalization(desc.AVCommandLineNode):
commandLine = 'aliceVision_rigLocalization {allParams}'

category = 'Utils'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ColorCheckerCorrection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import os.path


class ColorCheckerCorrection(desc.CommandLineNode):
class ColorCheckerCorrection(desc.AVCommandLineNode):
commandLine = 'aliceVision_utils_colorCheckerCorrection {allParams}'
size = desc.DynamicNodeSize('input')
# parallelization = desc.Parallelization(blockSize=40)
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ColorCheckerDetection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import os.path


class ColorCheckerDetection(desc.CommandLineNode):
class ColorCheckerDetection(desc.AVCommandLineNode):
commandLine = 'aliceVision_utils_colorCheckerDetection {allParams}'
size = desc.DynamicNodeSize('input')
# parallelization = desc.Parallelization(blockSize=40)
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ConvertMesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ConvertMesh(desc.CommandLineNode):
class ConvertMesh(desc.AVCommandLineNode):
commandLine = 'aliceVision_convertMesh {allParams}'

category = 'Utils'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ConvertSfMFormat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ConvertSfMFormat(desc.CommandLineNode):
class ConvertSfMFormat(desc.AVCommandLineNode):
commandLine = 'aliceVision_convertSfMFormat {allParams}'
size = desc.DynamicNodeSize('input')

Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/DepthMap.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class DepthMap(desc.CommandLineNode):
class DepthMap(desc.AVCommandLineNode):
commandLine = 'aliceVision_depthMapEstimation {allParams}'
gpu = desc.Level.INTENSIVE
size = desc.DynamicNodeSize('input')
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/DepthMapFilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class DepthMapFilter(desc.CommandLineNode):
class DepthMapFilter(desc.AVCommandLineNode):
commandLine = 'aliceVision_depthMapFiltering {allParams}'
gpu = desc.Level.NORMAL
size = desc.DynamicNodeSize('input')
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/DistortionCalibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class DistortionCalibration(desc.CommandLineNode):
class DistortionCalibration(desc.AVCommandLineNode):
commandLine = 'aliceVision_distortionCalibration {allParams}'
size = desc.DynamicNodeSize('input')

Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ExportAnimatedCamera.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ExportAnimatedCamera(desc.CommandLineNode):
class ExportAnimatedCamera(desc.AVCommandLineNode):
commandLine = 'aliceVision_exportAnimatedCamera {allParams}'

category = 'Export'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ExportColoredPointCloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ExportColoredPointCloud(desc.CommandLineNode):
class ExportColoredPointCloud(desc.AVCommandLineNode):
commandLine = 'aliceVision_exportColoredPointCloud {allParams}'

category = 'Export'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ExportMatches.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ExportMatches(desc.CommandLineNode):
class ExportMatches(desc.AVCommandLineNode):
commandLine = 'aliceVision_exportMatches {allParams}'
size = desc.DynamicNodeSize('input')

Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ExportMaya.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ExportMaya(desc.CommandLineNode):
class ExportMaya(desc.AVCommandLineNode):
commandLine = 'aliceVision_exportMeshroomMaya {allParams}'

category = 'Export'
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/FeatureExtraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class FeatureExtraction(desc.CommandLineNode):
class FeatureExtraction(desc.AVCommandLineNode):
commandLine = 'aliceVision_featureExtraction {allParams}'
size = desc.DynamicNodeSize('input')
parallelization = desc.Parallelization(blockSize=40)
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/FeatureMatching.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class FeatureMatching(desc.CommandLineNode):
class FeatureMatching(desc.AVCommandLineNode):
commandLine = 'aliceVision_featureMatching {allParams}'
size = desc.DynamicNodeSize('input')
parallelization = desc.Parallelization(blockSize=20)
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/FeatureRepeatability.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class FeatureRepeatability(desc.CommandLineNode):
class FeatureRepeatability(desc.AVCommandLineNode):
commandLine = 'aliceVision_samples_repeatabilityDataset {allParams}'
size = desc.DynamicNodeSize('input')
# parallelization = desc.Parallelization(blockSize=40)
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/GlobalSfM.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from meshroom.core import desc


class GlobalSfM(desc.CommandLineNode):
class GlobalSfM(desc.AVCommandLineNode):
commandLine = 'aliceVision_globalSfM {allParams}'
size = desc.DynamicNodeSize('input')

Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ImageMasking.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ImageMasking(desc.CommandLineNode):
class ImageMasking(desc.AVCommandLineNode):
commandLine = 'aliceVision_imageMasking {allParams}'
size = desc.DynamicNodeSize('input')
parallelization = desc.Parallelization(blockSize=40)
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ImageMatching.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from meshroom.core import desc


class ImageMatching(desc.CommandLineNode):
class ImageMatching(desc.AVCommandLineNode):
commandLine = 'aliceVision_imageMatching {allParams}'
size = desc.DynamicNodeSize('input')

Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ImageMatchingMultiSfM.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from meshroom.core import desc


class ImageMatchingMultiSfM(desc.CommandLineNode):
class ImageMatchingMultiSfM(desc.AVCommandLineNode):
commandLine = 'aliceVision_imageMatching {allParams}'
# use both SfM inputs to define Node's size
size = desc.MultiDynamicNodeSize(['input', 'inputB'])
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ImageProcessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def outputImagesValueFunct(attr):
return desc.Node.internalFolder + '*' + (outputExt or '.*')


class ImageProcessing(desc.CommandLineNode):
class ImageProcessing(desc.AVCommandLineNode):
commandLine = 'aliceVision_utils_imageProcessing {allParams}'
size = desc.DynamicNodeSize('input')
# parallelization = desc.Parallelization(blockSize=40)
Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/ImportKnownPoses.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meshroom.core import desc


class ImportKnownPoses(desc.CommandLineNode):
class ImportKnownPoses(desc.AVCommandLineNode):
commandLine = 'aliceVision_importKnownPoses {allParams}'
size = desc.DynamicNodeSize('sfmData')

Expand Down
2 changes: 1 addition & 1 deletion meshroom/nodes/aliceVision/KeyframeSelection.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from meshroom.core import desc


class KeyframeSelection(desc.CommandLineNode):
class KeyframeSelection(desc.AVCommandLineNode):
commandLine = 'aliceVision_utils_keyframeSelection {allParams}'

category = 'Utils'
Expand Down
Loading