From 7ff5664aa5fd3a244757ccae39dd63809de35dfe Mon Sep 17 00:00:00 2001 From: Command Date: Fri, 26 May 2023 20:56:00 +0800 Subject: [PATCH 1/3] add gpu support to Docker compiler --- seedemu/compiler/Docker.py | 40 +++++++++++++++++++++++++++++++++++++- seedemu/core/Node.py | 22 +++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/seedemu/compiler/Docker.py b/seedemu/compiler/Docker.py index 725485a47..9cea6c407 100644 --- a/seedemu/compiler/Docker.py +++ b/seedemu/compiler/Docker.py @@ -122,6 +122,7 @@ - net.ipv4.ip_forward=1 - net.ipv4.conf.default.rp_filter=0 - net.ipv4.conf.all.rp_filter=0 +{gpuDevices} privileged: true networks: {networks}{ports}{volumes} @@ -129,6 +130,34 @@ {labelList} """ +# DockerCompilerFileTemplates['compose_service_resources_limits'] = """\ +# deploy: +# resources: +# limits: +# cpus: {cpuLimit} +# memory: {memLimit} +# pids: {pidLimit} +# """ # TODO: try writing with yaml lib? + +# DockerCompilerFileTemplates['compose_service_resources_reservations'] = """\ +# deploy: +# resources: +# reservations: +# cpus: {cpuLimit} +# memory: {memLimit} +# pids: {pidLimit} +# """ # TODO: try writing with yaml lib? + +DockerCompilerFileTemplates['compose_service_resources_gpus'] = """\ + deploy: + resources: + reservations: + devices: + - driver: nvidia + capabilities: [gpu] + device_ids: [{deviceIDList}] +""" + DockerCompilerFileTemplates['compose_label_meta'] = """\ org.seedsecuritylabs.seedemu.meta.{key}: "{value}" """ @@ -835,6 +864,14 @@ def _compileNode(self, node: Node) -> str: netId = real_netname, address = address ) + + _gpuDevices = node.getGPUDevices() + gpuDevices = "" + if len(_gpuDevices) > 0: + gpuDevices = DockerCompilerFileTemplates['compose_service_resources_gpus'].format( + deviceIDList = ', '.join(f'"{device}"' for device in _gpuDevices) + ) + _ports = node.getPorts() ports = '' @@ -948,7 +985,8 @@ def _compileNode(self, node: Node) -> str: # privileged = 'true' if node.isPrivileged() else 'false', ports = ports, labelList = self._getNodeMeta(node), - volumes = volumes + volumes = volumes, + gpuDevices = gpuDevices ) def _compileNet(self, net: Network) -> str: diff --git a/seedemu/core/Node.py b/seedemu/core/Node.py index f621b83c7..65b89b5e2 100644 --- a/seedemu/core/Node.py +++ b/seedemu/core/Node.py @@ -229,6 +229,8 @@ class Node(Printable, Registrable, Configurable, Vertex): __name_servers: List[str] + __gpus: List[str] + def __init__(self, name: str, role: NodeRole, asn: int, scope: str = None): """! @brief Node constructor. @@ -779,6 +781,26 @@ def getInterfaces(self) -> List[Interface]: """ return self.__interfaces + def setGPUDevices(self, devices: List[str]): + """! + @brief Set the GPU device for the node. + + @param devices the new list of GPU ID. + + @returns self, for chaining API calls. + """ + self.__gpu = devices + + return self + + def getGPUDevices(self) -> List[str]: + """! + @brief Get the GPU device for the node. + + @returns list of GPU ID. + """ + return self.__gpu + def addSharedFolder(self, nodePath: str, hostPath: str) -> Node: """! @@brief Add a new shared folder between the node and host. From 1413062c9ea6d4240160fb33d642bd0dd0f2663d Mon Sep 17 00:00:00 2001 From: Command Date: Sun, 11 Jun 2023 17:14:02 +0800 Subject: [PATCH 2/3] fix typo --- seedemu/core/Node.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/seedemu/core/Node.py b/seedemu/core/Node.py index 65b89b5e2..9029143ce 100644 --- a/seedemu/core/Node.py +++ b/seedemu/core/Node.py @@ -270,6 +270,8 @@ def __init__(self, name: str, role: NodeRole, asn: int, scope: str = None): self.__name_servers = [] + self.__gpus = [] + def configure(self, emulator: Emulator): """! @brief configure the node. This is called when rendering. @@ -789,7 +791,7 @@ def setGPUDevices(self, devices: List[str]): @returns self, for chaining API calls. """ - self.__gpu = devices + self.__gpus = devices return self @@ -799,7 +801,7 @@ def getGPUDevices(self) -> List[str]: @returns list of GPU ID. """ - return self.__gpu + return self.__gpus def addSharedFolder(self, nodePath: str, hostPath: str) -> Node: """! From 55fb7f74bf9322b2689884da87e1976277e9c4a0 Mon Sep 17 00:00:00 2001 From: Command Date: Mon, 28 Aug 2023 22:22:30 +0800 Subject: [PATCH 3/3] add minimum working tensorflow-gpu example --- examples/D00-tensorflow/seed-compose.py | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 examples/D00-tensorflow/seed-compose.py diff --git a/examples/D00-tensorflow/seed-compose.py b/examples/D00-tensorflow/seed-compose.py new file mode 100644 index 000000000..92bb388ee --- /dev/null +++ b/examples/D00-tensorflow/seed-compose.py @@ -0,0 +1,53 @@ +from seedemu.core import Emulator, Binding, Filter, Action +from seedemu.layers import Base +from seedemu.compiler import Docker + +# Initialize the emulator and layers +emu = Emulator() +base = Base() + +# Create an autonomous system +as100 = base.createAutonomousSystem(100) + +# Create a network +as100.createNetwork('net0') + +# Create a host in the autonomous system and connect it to the network +host = as100.createHost('custom-host').joinNetwork('net0') +# use the first GPU only +host.setGPUDevices([0]) + +# download miniconda +host.addBuildCommand("mkdir -p ~/miniconda3 && curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh --output ~/miniconda3/miniconda.sh") +# # install miniconda +host.addBuildCommand("bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3 && rm -rf ~/miniconda3/miniconda.sh") +# host.addBuildCommand("curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba") +host.addBuildCommand("~/miniconda3/bin/conda install -n base conda-libmamba-solver && ~/miniconda3/bin/conda config --set solver libmamba") + +host.addBuildCommand("~/miniconda3/bin/conda init bash && ~/miniconda3/bin/conda init zsh") +# for chinese users +host.addBuildCommand("~/miniconda3/bin/conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/ && ~/miniconda3/bin/conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/ && ~/miniconda3/bin/conda config --set show_channel_urls yes") +host.addBuildCommand("~/miniconda3/bin/conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/") +# install deps +host.addBuildCommand("CONDA_OVERRIDE_CUDA=11.8 ~/miniconda3/bin/conda install tensorflow-gpu cudnn cudatoolkit=11.8") +# test is_gpu_available +host.appendStartCommand("~/miniconda3/bin/conda run python3 -c \"import tensorflow as tf; print('is_gpu_available': tf.test.is_gpu_available())\"") + +# Bind the base layer to the emulator +emu.addLayer(base) + +# Render the emulation +emu.render() + +# Compile the emulation +emu.compile(Docker(), './output', override=True) + +print(""" +Before running docker-compose, it is required to add GPU support to your Docker by: + Following Nvidia Container Toolkit Official Guide: + https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/user-guide.html + In some linux system, you can driectly install the toolkit via community package manager (e.g. AUR in arch) + https://wiki.archlinux.org/title/docker#With_NVIDIA_Container_Toolkit_.28recommended.29 + +When the container running, you are able to run your tensorflow code with GPU +""") \ No newline at end of file