{"id":5282,"date":"2018-10-23T12:14:21","date_gmt":"2018-10-23T10:14:21","guid":{"rendered":"https:\/\/new.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/"},"modified":"2023-03-08T16:04:23","modified_gmt":"2023-03-08T15:04:23","slug":"gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus","status":"publish","type":"post","link":"https:\/\/www.cloudandheat.com\/en\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/","title":{"rendered":"GPU cloud showcase: Neural Style Transfer parameter study using multiple Nvidia P100 GPUs"},"content":{"rendered":"<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">As a showcase for Cloud&amp;Heat\u2019s upcoming GPU cloud, this blog post summarizes the results of a hackathon organized by the IT team at Cloud&amp;Heat. We set up and ran a Deep Learning application on four Nvidia Tesla P100 GPUs which we have in our lab for testing purposes.<\/span><\/p>\n<h2><span style=\"font-size: 11.0pt; font-family: Montserrat;\">Introduction<\/span><\/h2>\n<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">Deep Learning is one branch of the current Machine Learning buzz that has a multitude of diverse applications as well as a hunger for computational resources. It is used for image and speech recognition, translation or autonomous driving, just to name a few. In terms of hardware, GPUs remain the workhorse of Deep Learning, since both training and inference make use of matrix operations which can be accelerated on these devices. Despite Google\u2019s TPU cloud, GPUs have a far greater application domain in other computationally demanding applications.<\/span><\/p>\n<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">The application that we will use here is termed Neural Style Transfer.<\/span><\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"size-full wp-image-2451\" src=\"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Blog-GPU-Cloud-showcase-01.jpg\" alt=\"Cloud and Heat | Blog | GPU Showcase | Green Computing | Edge Computing\" width=\"872\" height=\"199\" \/><\/p>\n<p>It uses deep neural networks to combine the content information of one image (left) with the artistic style of another (artwork in the middle) in order to make it look as if it was painted by the same artist<a href=\"https:\/\/www.cloudandheat.com\/blog\/gpu-showcase\/#fn1\"><sup>1<\/sup><\/a>.<\/p>\n<p>The idea to do this with deep learning was kicked off in 2015 by a paper called <a href=\"https:\/\/arxiv.org\/abs\/1508.06576\">A Neural Algorithm of Artistic Style<\/a> by Gatys et al.<\/p>\n<p>One basic ingredient is the usage of pre-trained deep convolutional neural networks such as the <a href=\"https:\/\/arxiv.org\/abs\/1409.1556\">VGG19 network<\/a>, which was trained for the <a href=\"http:\/\/image-net.org\/challenges\/LSVRC\/\">ImageNet Large Scale Visual Recognition Challenge (ILSVRC)<\/a> to categorize images into 1000 different classes. Since the trained networks have developed an abstract representation of objects as well as their visual representation, one can use that to interrogate the network when feeding it an image. Gatys et al. showed how to extract the essential content information (e.g. the features of a face), as well the artistic style (e.g. brush strokes). Now one can use an optimization algorithm starting from a white noise image (or the content image) with the objective that the final image shall have both the desired content and style.<\/p>\n<p>This optimization-based approach has the advantage that it can combine any given content with any style image. A faster approach was given by <a href=\"https:\/\/github.com\/jcjohnson\/fast-neural-style\">Johnson et al.<\/a> and later refined by <a href=\"http:\/\/arxiv.org\/abs\/1607.08022\">Ulyanov et al.<\/a> where they train a second \u201ctransfer network\u201d to solve the optimization in one forward pass. Once trained, the method is very fast, in fact one can even transfer videos in real time. However, the style image and all free parameters of the transfer are fixed. Also, to train the transfer network, one needs a large database of content images. Since we need a method to quickly load our GPUs, we go with Gatys\u2019s method, were we only need one content and one style image.<\/p>\n<p>There are many implementations of Gatys\u2019 method such as <a href=\"https:\/\/github.com\/keras-team\/keras\/blob\/master\/examples\/neural_style_transfer.py\">this from Keras<\/a>, <a href=\"https:\/\/github.com\/jcjohnson\/fast-neural-style\/blob\/master\/slow_neural_style.lua\">this from Johnson<\/a> or <a href=\"https:\/\/github.com\/anishathalye\/neural-style\">this from Athalye<\/a>. We chose the latter <a href=\"https:\/\/www.tensorflow.org\">TensorFlow<\/a> <a href=\"https:\/\/github.com\/anishathalye\/neural-style\">implementation<\/a> since it has a couple of parameters to play with. We use this as a nice showcase to illustrate a problem that <em>everybody<\/em> has to solve: parameter tuning. There are at least six parameters in our chosen implementation that influence the generated image. The ratio in which to weight style and content is just one example (hint: 50:50 is not it). With the computational power we have available, we can run many style transfer calculations in an orderly fashion to scan for the best parameters. Note that also the fast method of Johnson from above has to do this first in order to define the objective function for training the transfer network.<\/p>\n<p>There are also newer advanced methods for Style Transfer based on Generative Adversarial Networks (<a href=\"https:\/\/junyanz.github.io\/CycleGAN\/\">CycleGANs<\/a>) with impressive results which we won\u2019t use here, however.<\/p>\n<p>Before we go on, we\u2019ll tell you about the hardware and software that we have used. If that is not your cup of tea then skip ahead \u2014 we also have Jupyter notebooks down there!<\/p>\n<h2>Hardware and Operating System<\/h2>\n<p>Our test machine is composed of a Supermicro chassis, a Supermicro X10DRG-OT+-CPU motherboard, 24 GB RAM and 24 CPU cores in a dual socket Intel Xeon E5-2650 setup. The case houses 4 Nvidia Tesla P100 GPUs (Pascal architecture), connected via PCIe (no NVLink). These cards are datacenter-grade devices, packing 16 GB of RAM per card and having 5, 11 and 21 Tflops <a href=\"https:\/\/www.nvidia.com\/en-us\/data-center\/tesla-p100\">peak performance<\/a> in double (64bit), single (32bit) and half (16bit) precision mode, respectively.<\/p>\n<p>We run Ubuntu 16.04 LTS on the bare metal host. In order to showcase the cloud usage scenario, we spin up a VM using 20 GB of RAM and 20 vCPUs, also running an Ubuntu 16.04 image. The machine resides in our lab and is not integrated into our <a href=\"https:\/\/www.cloudandheat.com\/our-solutions\/public-cloud-and-heat\/\">OpenStack cloud<\/a>, which is why we run it \u201cby hand\u201d using <a href=\"https:\/\/www.qemu.org\/\">QEM<\/a> in <a href=\"https:\/\/www.linux-kvm.org\/page\/Main_Page\">KVM<\/a> mode driven by <a href=\"https:\/\/libvirt.org\/\">libvirt<\/a><sup>]<\/sup> and remote controlled by <a href=\"https:\/\/virt-manager.org\/\">virt-manager<\/a>. Each of the four P100s is attached as PCI device to the VM (GPU pass-through). We also pass all host CPU features through to the VM for maximal performance.<\/p>\n<h2>TensorFlow and CUDA<\/h2>\n<p>There are <a href=\"https:\/\/hub.docker.com\/r\/tensorflow\/tensorflow\/\">TensorFlow Docker images<\/a> available, but we show here that it is easy to install TensorFlow along with all dependencies. After all, installing stuff is what our DevOps engineers do all day!<\/p>\n<p>What we need to install for TensorFlow to work with the GPUs is<\/p>\n<ul>\n<li>the Nvidia device driver<\/li>\n<li>the <a href=\"https:\/\/developer.nvidia.com\/cuda-zone\">CUDA Toolkit<\/a> with GPU-enabled numerical libraries and more<\/li>\n<li><a href=\"https:\/\/developer.nvidia.com\/cudnn\">cuDNN<\/a>: Nvidia library with GPU-accelerated primitives for deep neural nets<\/li>\n<\/ul>\n<p>Since TensorFlow is C++ wrapped with Python, we can install it using <a href=\"https:\/\/pypi.org\/project\/tensorflow-gpu\/\">pip<\/a>. The current CUDA version is 10.0, but TensorFlow supports 9.0 at the time of writing. Ubuntu 16.04 ships CUDA 7 (nvidia-cuda-dev package), so we will install <a href=\"https:\/\/developer.nvidia.com\/cuda-downloads\">directly from Nvidia<\/a>.<\/p>\n<pre><code>$ wget http:\/\/developer.download.nvidia.com\/compute\/cuda\/repos\/ubuntu1604\/x86_64\/cuda-repo-ubuntu1604_9.0.176-1_amd64.deb\n$ sudo apt-key adv --fetch-keys http:\/\/developer.download.nvidia.com\/compute\/cuda\/repos\/ubuntu1604\/x86_64\/7fa2af80.pub\n$ sudo dpkg -i cuda-repo-ubuntu1604_9.0.176-1_amd64.deb\n$ sudo apt-get update\n$ sudo apt-get --no-install-recommends install cuda-9-0<\/code><\/pre>\n<p>Installing CUDA packages should also pull a recent driver package, e.g. nvidia-410.<\/p>\n<p>TensorFlow from <code>pip<\/code> is linked against cuDNN. You can <a href=\"https:\/\/docs.nvidia.com\/deeplearning\/sdk\/cudnn-install\/\">get this from Nvidia<\/a> after registration, which lets you download a Debian package.<\/p>\n<pre><code>$ sudo dpkg -i libcudnn7_7.2.1.38-1+cuda9.0_amd64.deb<\/code><\/pre>\n<p>Now we can install TensorFlow. We need to make sure to use the GPU-enabled version <code>tensorflow-gpu<\/code>:<\/p>\n<pre><code>$ sudo apt-get --no-install-recommends install python3-pip python3-wheel python3-setuptools\n$ pip3 install tensorflow-gpu scipy matplotlib Pillow pandas psweep<\/code><\/pre>\n<p>While we were at it, we installed a couple of dependencies for the Style Transfer code (see below), namely <code>scipy<\/code>,<code>matplotlib<\/code> and the <code>Pillow<\/code> implementation of the Python Imaging Library (PIL). We also install <code>psweep<\/code> to help run and evaluate the parameter study.<\/p>\n<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">That\u2019s it!<\/span><\/p>\n<h2 id=\"neural-style-implementation\">Neural Style implementation<\/h2>\n<p>We <a href=\"https:\/\/github.com\/elcorto\/neural-style\">forked<\/a> the TensorFlow implementation of the Style Transfer algorithm described above and adapted it to our needs (basically convergence monitoring). The installation is straight forward. We just pull the repo and download trained weights of the VGG19 network:<\/p>\n<pre><code>$ git clone https:\/\/github.com\/elcorto\/neural-style\n$ cd neural-style\n$ wget http:\/\/www.vlfeat.org\/matconvnet\/models\/beta16\/imagenet-vgg-verydeep-19.mat<\/code><\/pre>\n<p>The executable which we use is neural-style\/neural_style.py.<\/p>\n<p>The algorithm uses the <a href=\"https:\/\/arxiv.org\/abs\/1412.6980\">Adam optimizer<\/a>, and the objective function to be optimized has three parts: the <code>style_loss<\/code> measures how well the output image reproduces the style of the style image, the <code>content_loss<\/code> does the same for content. The third component is the <code>tv_loss<\/code> (total variation regularization loss) which measures how smooth the image looks. The total loss is a weighted sum: <code>total_loss<\/code> = <code>tv_weight<\/code> * <code>tv_loss<\/code> + <code>content_weight<\/code> * <code>content_loss<\/code> + <code>style_weight<\/code> * <code>style_loss<\/code>.<\/p>\n<h2>Parameter tuning results<\/h2>\n<p>Our Style Transfer algorithm has many options, of which the following have been kept constant:<\/p>\n<ul>\n<li><code>width = 512<\/code>: Output image width. The height is determined from the content image\u2019s aspect ratio. Our content and output images have 512\u00d7532 pixel.<\/li>\n<li><code>iterations<\/code> = 1000: Most runs are converged after ~500 iterations, but with 1000, we are on the safe side.<\/li>\n<li><code>initial<\/code> = None: We use a random white noise image for each run and not the content image. Because of this, no run, even with unchanged parameters, will have the exact same result.<\/li>\n<li><code>pooling<\/code> = max: We use the default max pooling (instead of average pooling).<\/li>\n<\/ul>\n<p>We scan the following parameters of the Style Transfer algorithm in order to find the visually most appealing results:<\/p>\n<ul>\n<li>learning_rate: The learning rate is the step size of the optimizer. To small values result in slow convergence, while too large values cause large jumps in the objective function value (<code>total_loss<\/code>) and unstable convergence.<\/li>\n<li><code>style_scales<\/code>: scale factor of the style image w.r.t. the output image, can select smaller or larger features in the style image<\/li>\n<li><code>style_weight<\/code>: weight for <code>style_loss<\/code>, we keep <code>content_weight<\/code> = 1, so this is the ratio of style\/content mixing in the final image<\/li>\n<li><code>tv_weight<\/code>: weight of <code>tv_loss<\/code><\/li>\n<li><code>content_weight_blend<\/code>: mixing factor for combining two content layers <code>conv4_2<\/code> * <code>content_weight_blend<\/code> + <code>conv5_2<\/code> * (1 &#8211; <code>content_weight_blend<\/code>), has an effect similar to <code>style_weight<\/code><\/li>\n<li>&gt;code&gt;style_layer_weight_exp: style layer weight exponential increase, similar to <code>content_weight_blend<\/code> but for style layers, <code>weight(layer&lt;n+1&gt;)<\/code> = <code>weight_exp*weight(layer&lt;n&gt;)<\/code>, low values favor fine features of the style image over coarse ones<\/li>\n<\/ul>\n<p>As you can see, the parameters above do all influence the final image, but even if one knows the general effect of a parameter, one needs a lot of test runs to find a good parameter combination. Side note: This is in itself an optimization problem. If we had a good metric to calculate how \u201cvisually appealing\u201d an image is, we could let an algorithm find the best setting. But we don\u2019t have that, so we need manual visual inspection.<\/p>\n<p>Let\u2019s say we like to test 10 values for each of the six parameter. Doing a brute force sampling would result in one million calculations. With one minute per run, this would take 10^6\/60\/24\/365 = 1.9 years on one GPU. A bit long.<\/p>\n<p>Assuming that the parameter effects are largely independent, we can take a much simpler approach: We use a set of default parameter values and vary each parameter independently. With 10 values per parameter, we would need only 60 runs, e.g. one hour on one GPU. We have four GPUs and can thus start four independent runs in parallel, which drops the calculation time to 15 min.<\/p>\n<p>Here are the default parameters that we used.<\/p>\n<p>Constant for all runs:<\/p>\n<table>\n<tbody>\n<tr>\n<td>width<\/td>\n<td>512<\/td>\n<\/tr>\n<tr>\n<td>iterations<\/td>\n<td>1000<\/td>\n<\/tr>\n<tr>\n<td>initial<\/td>\n<td>None<\/td>\n<\/tr>\n<tr>\n<td>pooling<\/td>\n<td>\u2018max\u2019<\/td>\n<\/tr>\n<tr>\n<td>content_weight<\/td>\n<td>1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Defaults of parameters which have been varied:<\/p>\n<table>\n<tbody>\n<tr>\n<td>learning_rate<\/td>\n<td>10<\/td>\n<\/tr>\n<tr>\n<td>style_scales<\/td>\n<td>1<\/td>\n<\/tr>\n<tr>\n<td>content_weight_blend<\/td>\n<td>0.2<\/td>\n<\/tr>\n<tr>\n<td>style_weight<\/td>\n<td>10<\/td>\n<\/tr>\n<tr>\n<td>tv_weight<\/td>\n<td>100<\/td>\n<\/tr>\n<tr>\n<td>style_layer_weight_exp<\/td>\n<td>1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>We performed 252 runs in total, sampling all parameters with 13 to 75 values. This takes about an hour on four GPUs. Here are some example results showing just 5 values (columns) per parameter (rows).<\/p>\n<p><img decoding=\"async\" class=\" wp-image-2452\" src=\"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Blog-GPU-Cloud-showcase-02.jpg\" alt=\"Cloud and Heat | Blog | GPU Showcase | Green Computing | Edge Computing\" width=\"598\" height=\"558\" \/><\/p>\n<p>We have put the parameter study database, a compressed version of all result images and all scripts which we used to run the parameter study and evaluate the data in a <a href=\"https:\/\/github.com\/CloudAndHeat\/style_transfer_parameter_sweep\">GitHub repo<\/a>, along with a <a href=\"https:\/\/jupyter.org\/\">Jupyter<\/a> notebook where you can explore the full dataset. To do this interactively in your browser, start <a href=\"https:\/\/mybinder.org\/v2\/gh\/CloudAndHeat\/style_transfer_parameter_sweep\/master?filepath=interactive.ipynb\">the Jupyter notebook here<\/a>. This will use <a href=\"https:\/\/mybinder.org\/\">Binder<\/a> to start a Docker container, checkout the repo, install all dependencies, start a Jupyter kernel and server and show you the notebook. If an already built Docker image of the repo is found, then this makes things start quicker. Once the notebook is loaded, click \u201cRun\u201d. It will take some seconds to render and download all six visualizations, which will look like this:<\/p>\n<p><img decoding=\"async\" class=\" wp-image-2453\" src=\"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Blog-GPU-Cloud-showcase-03.jpg\" alt=\"Cloud and Heat | Blog | GPU Showcase | Green Computing | Edge Computing\" width=\"595\" height=\"693\" \/><\/p>\n<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">Then use the sliders to change the parameter values and observe how they affect the image.<\/span><\/p>\n<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">You can also run that locally:<\/span><\/p>\n<pre><code>$ mkvirtualenv styletransfer -p \/usr\/bin\/python3\n$ git clone https:\/\/github.com\/CloudAndHeat\/style_transfer_parameter_sweep\n$ cd style_transfer_parameter_sweep\n$ pip3 install -r requirements.txt\n$ pip3 install notebook\n$ jupyter notebook interactive.ipynb<\/code><\/pre>\n<h2>Performance<\/h2>\n<p>We ran preliminary CPU-only tests on our VM (20 vCPUs) for 1000 iterations of optimization, using the same image (512\u00d7532 pixel) as in all GPU runs. Note that TensorFlow uses all available cores by default, so any fair comparison must take the number of cores and the CPU type into account. We also ran a single-CPU test by forcing TensorFlow onto one CPU (using taskset -c 0 for CPU #0).<\/p>\n<table>\n<tbody>\n<tr>\n<td>1 vCPU<\/td>\n<td>~4 hours 30 min (270 min)<\/td>\n<\/tr>\n<tr>\n<td>20 vCPU<\/td>\n<td>45 min<\/td>\n<\/tr>\n<tr>\n<td>20 vCPU + 1 GPU<\/td>\n<td>1 min<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The CPU-only speedup between 1 and 20 CPUs is only 270\/45 = 6 instead of theoretically 20, which means that TensorFlow doesn\u2019t scale well.<\/p>\n<p>The run using one P100 finishes within 1 minute, so we have a factor 45 speedup! This is huge. Similar results have been obtained by a <a href=\"https:\/\/www.microway.com\/hpc-tech-tips\/deep-learning-benchmarks-nvidia-tesla-p100-16gb-pcie-tesla-k80-tesla-m40-gpus\/\">detailed Deep Learning benchmark<\/a> performed by Microway, which covers the P100 and other Nvidia cards. Below we will show how to additionally leverage <em>multiple<\/em> GPUs with linear scaling.<\/p>\n<p>Note that the image size has a large impact on the run time, since larger images result in larger matrices that must be processed.<\/p>\n<h2>Running on multiple GPUs<\/h2>\n<p>We use the <a href=\"https:\/\/pypi.org\/project\/psweep\/\">psweep<\/a> Python package to run the parameter study. It takes all parameter sets, runs the Style Transfer code for each and writes a database which <a href=\"https:\/\/github.com\/CloudAndHeat\/style_transfer_parameter_sweep\/blob\/master\/vistools.py#L15\">we use to analyze the runs later<\/a>. It can use <a href=\"https:\/\/docs.python.org\/3.6\/library\/multiprocessing.html\">multiprocessing<\/a> to run each parameter set workload in parallel, which is what we do here. Since our use case is many <em>independent<\/em> calculations, multiprocessing is the ideal tool for parallelization, without using NVLink and multi-GPU TensorFlow. Also, this approach will scale linearly with the number of available GPUs.<\/p>\n<p>We ran into two issues with TensorFlow. The first is that when running one instance of the Style Transfer code, TensorFlow will allocate memory on all four GPUs, even though it uses only one for computation. We can see this in the output of the nvidia-smi CLI tool.<\/p>\n<pre><code>+-----------------------------------------------------------------------------+\n| NVIDIA-SMI 410.48                 Driver Version: 410.48                    |\n|-------------------------------+----------------------+----------------------+\n| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |\n| Fan  Temp  Perf  Pwr:Usage\/Cap|         Memory-Usage | GPU-Util  Compute M. |\n|===============================+======================+======================|\n|   0  Tesla P100-PCIE...  Off  | 00000000:00:09.0 Off |                    0 |\n| N\/A   52C    P0   199W \/ 250W |  15639MiB \/ 16280MiB |     98%      Default |\n+-------------------------------+----------------------+----------------------+\n|   1  Tesla P100-PCIE...  Off  | 00000000:00:0A.0 Off |                    0 |\n| N\/A   37C    P0    35W \/ 250W |  15485MiB \/ 16280MiB |      0%      Default |\n+-------------------------------+----------------------+----------------------+\n|   2  Tesla P100-PCIE...  Off  | 00000000:00:0B.0 Off |                    0 |\n| N\/A   38C    P0    32W \/ 250W |  15485MiB \/ 16280MiB |      0%      Default |\n+-------------------------------+----------------------+----------------------+\n|   3  Tesla P100-PCIE...  Off  | 00000000:00:0C.0 Off |                    0 |\n| N\/A   45C    P0    34W \/ 250W |  15485MiB \/ 16280MiB |      0%      Default |\n+-------------------------------+----------------------+----------------------+\n+-----------------------------------------------------------------------------+\n| Processes:                                                       GPU Memory |\n|  GPU       PID   Type   Process name                             Usage      |\n|=============================================================================|\n|    0     26216      C   python3                                    15629MiB |\n|    1     26216      C   python3                                    15475MiB |\n|    2     26216      C   python3                                    15475MiB |\n|    3     26216      C   python3                                    15475MiB |\n+-----------------------------------------------------------------------------+<\/code><\/pre>\n<p>Note that the memory of all four GPUs is used, but only one has load (column GPU-Util). This is a <a href=\"https:\/\/github.com\/tensorflow\/tensorflow\/issues\/3644\">known<\/a> <a href=\"https:\/\/github.com\/tensorflow\/tensorflow\/issues\/5066\">issue<\/a>.<\/p>\n<p>The second problem to solve is how to schedule tasks onto different GPUs when using multiprocessing. Our first approach was to use TensorFlow\u2019s <a href=\"https:\/\/www.tensorflow.org\/versions\/r1.10\/api_docs\/python\/tf\/device\">tf.device context manager<\/a> in our fork of the Style Transfer code to select the GPU. This works as advertised. But we ran into the above issue again: We get OOM (out of memory) errors since, even if we schedule a second task correctly (one per GPU), memory is already allocated by the first task.<\/p>\n<p>The solution to both problems is the environment variable CUDA_VISIBLE_DEVICES, which can be set to the ID of a GPU, for us 0,1,2 or 3. When running our code with this, we do not need tf.device at all, since the whole process will see only one GPU and allocate only on this. Inside the process, TensorFlow always sees one GPU only with ID 0, as in tf.device(&#8218;\/device:GPU:0&#8216;), which is default.<\/p>\n<p>The final piece to figure out is how to tell a process which GPU to use. There is a simple hack to do this. As it turns out, multiprocessing names the processes it starts something like ForkPoolWorker-1, ForkPoolWorker-2, etc. So we just have to parse the process name and turn that into the GPU ID. The code snippet below shows how we do this.<\/p>\n<pre><code>import multiprocessing\ndef worker(pset):\n    \"\"\"Run Style Transfer code for one parameter set (`pset`).\"\"\"\n    ... here be code ...\ndef gpu_worker(pset):\n    \"\"\"Select GPU device based on multiprocessing process name.\"\"\"\n    name = multiprocessing.current_process().name\n    # will set CUDA_VISIBLE_DEVICES={0,1,2,...}\n    pset['gpu_device'] = int(name.replace('ForkPoolWorker-','')) - 1\n    pset.update(worker(pset))\n    return pset\nif __name__ == '__main__':\n    with multiprocessing.Pool(4) as pool:\n        pool.map(gpu_worker, params)<\/code><\/pre>\n<p>This is an extremely simple trick to bind a multiprocessing process to a GPU. It is guaranteed to never oversubscribe a GPU since all four process will live as long as the main script runs, i.e. the binding is defined at startup and doesn\u2019t change during the script\u2019s run time.<\/p>\n<p>Note that the pool.map() part above is not exactly how we do it, since we pass gpu_worker and params to psweep.run() which takes care of that. Here is <a href=\"https:\/\/github.com\/CloudAndHeat\/style_transfer_parameter_sweep\/blob\/master\/10run.py\">the full script we used<\/a>.<\/p>\n<p>This is how it looks like in nvidia-smi<\/p>\n<pre><code>+-----------------------------------------------------------------------------+\n| NVIDIA-SMI 410.48                 Driver Version: 410.48                    |\n|-------------------------------+----------------------+----------------------+\n| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |\n| Fan  Temp  Perf  Pwr:Usage\/Cap|         Memory-Usage | GPU-Util  Compute M. |\n|===============================+======================+======================|\n|   0  Tesla P100-PCIE...  Off  | 00000000:00:09.0 Off |                    0 |\n| N\/A   63C    P0   182W \/ 250W |  15639MiB \/ 16280MiB |     98%      Default |\n+-------------------------------+----------------------+----------------------+\n|   1  Tesla P100-PCIE...  Off  | 00000000:00:0A.0 Off |                    0 |\n| N\/A   57C    P0   198W \/ 250W |  15639MiB \/ 16280MiB |     98%      Default |\n+-------------------------------+----------------------+----------------------+\n|   2  Tesla P100-PCIE...  Off  | 00000000:00:0B.0 Off |                    0 |\n| N\/A   65C    P0   199W \/ 250W |  15639MiB \/ 16280MiB |     98%      Default |\n+-------------------------------+----------------------+----------------------+\n|   3  Tesla P100-PCIE...  Off  | 00000000:00:0C.0 Off |                    0 |\n| N\/A   58C    P0   213W \/ 250W |  15639MiB \/ 16280MiB |     97%      Default |\n+-------------------------------+----------------------+----------------------+\n+-----------------------------------------------------------------------------+\n| Processes:                                                       GPU Memory |\n|  GPU       PID   Type   Process name                             Usage      |\n|=============================================================================|\n|    0     21788      C   python3                                    15629MiB |\n|    1     21752      C   python3                                    15629MiB |\n|    2     21821      C   python3                                    15629MiB |\n|    3     21855      C   python3                                    15629MiB |\n+-----------------------------------------------------------------------------+<\/code><\/pre>\n<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">Four GPUs at full load, this is what we like!<\/span><\/p>\n<h2><span style=\"font-size: 11.0pt; font-family: Montserrat;\">Conclusion<\/span><\/h2>\n<p><span style=\"font-size: 11.0pt; font-family: Montserrat;\">GPUs are without doubt powerful devices for numerical calculations with impressive speedups, when combined with GPU-enabled software. We showed how to set up a GPU machine and install TensorFlow and its dependencies. In the toy use case above, we demonstrated how to easily leverage multiple GPUs with plain Python multiprocessing built-in tools.<\/span><\/p>\n<p>The &#8222;Candy&#8220; style image is the same used by <a href=\"https:\/\/github.com\/jcjohnson\/fast-neural-style\">Johnson&#8217;s implementation<\/a>, the &#8222;selfie&#8220; content image is <a href=\"https:\/\/www.pexels.com\/photo\/black-chimpanzee-smiling-50582\/\">this<\/a> from the <a href=\"https:\/\/www.pexels.com\">Pexels database of public domain images<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This showcase is a result of a hackathon organised by the IT team at Cloud&amp;Heat.<\/p>","protected":false},"author":2,"featured_media":5287,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","inline_featured_image":false,"footnotes":""},"categories":[83,82],"tags":[],"class_list":["post-5282","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cloud-services","category-use-case"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Cloud&amp;Heat | GPU cloud showcase | Neural Style Transfer parameter<\/title>\n<meta name=\"description\" content=\"Cloud&amp;Heat Technologies makes sustainability and security the drivers of digital innovation. | Future of compute | Cloud Security | GPU cloud showcase\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.cloudandheat.com\/en\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cloud&amp;Heat | GPU cloud showcase | Neural Style Transfer parameter\" \/>\n<meta property=\"og:description\" content=\"Cloud&amp;Heat Technologies makes sustainability and security the drivers of digital innovation. | Future of compute | Cloud Security | GPU cloud showcase\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.cloudandheat.com\/en\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloud &amp; Heat\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/CloudandHeat\" \/>\n<meta property=\"article:published_time\" content=\"2018-10-23T10:14:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-03-08T15:04:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"512\" \/>\n\t<meta property=\"og:image:height\" content=\"532\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Clemens M\u00fcller\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@cloudandheat\" \/>\n<meta name=\"twitter:site\" content=\"@cloudandheat\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Clemens M\u00fcller\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/\"},\"author\":{\"name\":\"Clemens M\u00fcller\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#\\\/schema\\\/person\\\/ba09b0c184d05469ca875d2cb5ba730a\"},\"headline\":\"GPU cloud showcase: Neural Style Transfer parameter study using multiple Nvidia P100 GPUs\",\"datePublished\":\"2018-10-23T10:14:21+00:00\",\"dateModified\":\"2023-03-08T15:04:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/\"},\"wordCount\":2523,\"publisher\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.cloudandheat.com\\\/wp-content\\\/uploads\\\/2023\\\/01\\\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png\",\"articleSection\":[\"Cloud Services\",\"Use Case\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/\",\"url\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/\",\"name\":\"Cloud&Heat | GPU cloud showcase | Neural Style Transfer parameter\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.cloudandheat.com\\\/wp-content\\\/uploads\\\/2023\\\/01\\\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png\",\"datePublished\":\"2018-10-23T10:14:21+00:00\",\"dateModified\":\"2023-03-08T15:04:23+00:00\",\"description\":\"Cloud&Heat Technologies makes sustainability and security the drivers of digital innovation. | Future of compute | Cloud Security | GPU cloud showcase\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.cloudandheat.com\\\/wp-content\\\/uploads\\\/2023\\\/01\\\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png\",\"contentUrl\":\"https:\\\/\\\/www.cloudandheat.com\\\/wp-content\\\/uploads\\\/2023\\\/01\\\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png\",\"width\":512,\"height\":532},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/www.cloudandheat.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GPU cloud showcase: Neural Style Transfer parameter study using multiple Nvidia P100 GPUs\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#website\",\"url\":\"https:\\\/\\\/www.cloudandheat.com\\\/\",\"name\":\"Cloud & Heat Technolgies GmbH\",\"description\":\"Cloud-Service- und Cloud-Technologie-Provider\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#organization\"},\"alternateName\":\"Cloud and Heat Technologies GmbH\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.cloudandheat.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#organization\",\"name\":\"Cloud&Heat Technologies GmbH\",\"url\":\"https:\\\/\\\/www.cloudandheat.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.cloudandheat.com\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/logo.svg\",\"contentUrl\":\"https:\\\/\\\/www.cloudandheat.com\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/logo.svg\",\"width\":907,\"height\":1782,\"caption\":\"Cloud&Heat Technologies GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/CloudandHeat\",\"https:\\\/\\\/x.com\\\/cloudandheat\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.cloudandheat.com\\\/#\\\/schema\\\/person\\\/ba09b0c184d05469ca875d2cb5ba730a\",\"name\":\"Clemens M\u00fcller\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/350f97f507a0c231669ebf507b516e705ead54569fde6f8537dee0acc251ee2d?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/350f97f507a0c231669ebf507b516e705ead54569fde6f8537dee0acc251ee2d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/350f97f507a0c231669ebf507b516e705ead54569fde6f8537dee0acc251ee2d?s=96&d=mm&r=g\",\"caption\":\"Clemens M\u00fcller\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Cloud&amp;Heat | GPU cloud showcase | Neural Style Transfer parameter","description":"Cloud&amp;Heat Technologies makes sustainability and security the drivers of digital innovation. | Future of compute | Cloud Security | GPU cloud showcase","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.cloudandheat.com\/en\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/","og_locale":"en_GB","og_type":"article","og_title":"Cloud&Heat | GPU cloud showcase | Neural Style Transfer parameter","og_description":"Cloud&Heat Technologies makes sustainability and security the drivers of digital innovation. | Future of compute | Cloud Security | GPU cloud showcase","og_url":"https:\/\/www.cloudandheat.com\/en\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/","og_site_name":"Cloud &amp; Heat","article_publisher":"https:\/\/www.facebook.com\/CloudandHeat","article_published_time":"2018-10-23T10:14:21+00:00","article_modified_time":"2023-03-08T15:04:23+00:00","og_image":[{"width":512,"height":532,"url":"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png","type":"image\/png"}],"author":"Clemens M\u00fcller","twitter_card":"summary_large_image","twitter_creator":"@cloudandheat","twitter_site":"@cloudandheat","twitter_misc":{"Written by":"Clemens M\u00fcller","Estimated reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/#article","isPartOf":{"@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/"},"author":{"name":"Clemens M\u00fcller","@id":"https:\/\/www.cloudandheat.com\/#\/schema\/person\/ba09b0c184d05469ca875d2cb5ba730a"},"headline":"GPU cloud showcase: Neural Style Transfer parameter study using multiple Nvidia P100 GPUs","datePublished":"2018-10-23T10:14:21+00:00","dateModified":"2023-03-08T15:04:23+00:00","mainEntityOfPage":{"@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/"},"wordCount":2523,"publisher":{"@id":"https:\/\/www.cloudandheat.com\/#organization"},"image":{"@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/#primaryimage"},"thumbnailUrl":"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png","articleSection":["Cloud Services","Use Case"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/","url":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/","name":"Cloud&amp;Heat | GPU cloud showcase | Neural Style Transfer parameter","isPartOf":{"@id":"https:\/\/www.cloudandheat.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/#primaryimage"},"image":{"@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/#primaryimage"},"thumbnailUrl":"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png","datePublished":"2018-10-23T10:14:21+00:00","dateModified":"2023-03-08T15:04:23+00:00","description":"Cloud&amp;Heat Technologies makes sustainability and security the drivers of digital innovation. | Future of compute | Cloud Security | GPU cloud showcase","breadcrumb":{"@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/#primaryimage","url":"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png","contentUrl":"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2023\/01\/2018-10-23-Cloud-and-Heat-Blog-GPU-cloud-showcase-1.png","width":512,"height":532},{"@type":"BreadcrumbList","@id":"https:\/\/www.cloudandheat.com\/gpu-cloud-showcase-neural-style-transfer-parameter-study-using-multiple-nvidia-p100-gpus\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/www.cloudandheat.com\/"},{"@type":"ListItem","position":2,"name":"GPU cloud showcase: Neural Style Transfer parameter study using multiple Nvidia P100 GPUs"}]},{"@type":"WebSite","@id":"https:\/\/www.cloudandheat.com\/#website","url":"https:\/\/www.cloudandheat.com\/","name":"Cloud &amp; Heat Technolgies GmbH","description":"Cloud service and cloud technology providers","publisher":{"@id":"https:\/\/www.cloudandheat.com\/#organization"},"alternateName":"Cloud and Heat Technologies GmbH","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.cloudandheat.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/www.cloudandheat.com\/#organization","name":"Cloud&amp;Heat Technologies GmbH","url":"https:\/\/www.cloudandheat.com\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.cloudandheat.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2022\/08\/logo.svg","contentUrl":"https:\/\/www.cloudandheat.com\/wp-content\/uploads\/2022\/08\/logo.svg","width":907,"height":1782,"caption":"Cloud&Heat Technologies GmbH"},"image":{"@id":"https:\/\/www.cloudandheat.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/CloudandHeat","https:\/\/x.com\/cloudandheat"]},{"@type":"Person","@id":"https:\/\/www.cloudandheat.com\/#\/schema\/person\/ba09b0c184d05469ca875d2cb5ba730a","name":"Clemens M\u00fcller","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/350f97f507a0c231669ebf507b516e705ead54569fde6f8537dee0acc251ee2d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/350f97f507a0c231669ebf507b516e705ead54569fde6f8537dee0acc251ee2d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/350f97f507a0c231669ebf507b516e705ead54569fde6f8537dee0acc251ee2d?s=96&d=mm&r=g","caption":"Clemens M\u00fcller"}}]}},"_links":{"self":[{"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/posts\/5282","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/comments?post=5282"}],"version-history":[{"count":0,"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/posts\/5282\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/media\/5287"}],"wp:attachment":[{"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/media?parent=5282"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/categories?post=5282"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudandheat.com\/en\/wp-json\/wp\/v2\/tags?post=5282"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}