Monitorando um cluster da GPU

4

Eu tenho 10 servidores rodando no Ubuntu 14.04 x64. Cada servidor tem algumas GPUs da Nvidia. Estou à procura de um programa de monitoramento que permita visualizar o uso da GPU em todos os servidores.

    
por Franck Dernoncourt 21.04.2016 / 01:24

4 respostas

2

munin tem pelo menos um plugin para monitoramento de GPUs nvidia (que usa o utilitário nvidia-smi para coletar seus dados).

Você pode configurar um servidor munin (talvez em um dos servidores GPU ou no nó principal do cluster) e, em seguida, instalar o cliente munin-node e o plug-in nvidia (além de outros plug-ins que você possa ter) interessado em) em cada um dos seus servidores de GPU.

Isso permitiria que você analisasse detalhadamente os dados munin de cada servidor ou visualizasse uma visão geral dos dados da nvidia para todos os servidores. Isso incluiria gráficos que registram alterações em, por exemplo, temperatura da GPU ao longo do tempo

Caso contrário, você poderia escrever um script para usar o ssh (ou pdsh ) para executar o utilitário nvidia-smi no cada servidor, extraia os dados desejados e os apresente no formato que desejar.

    
por 21.04.2016 / 13:34
2

Você pode usar o software de monitoramento ganglia (gratuito, código aberto). Ele tem um número de módulos métricos de DSM do Gmond Python contribuídos pelo usuário , incluindo um módulo GPU Nvidia ( /ganglia/gmond_python_modules/gpu/nvidia/ ).

Sua arquitetura é típica de um software de monitoramento de cluster:

( fonte da imagem )

É simples de instalar (~ 30 minutos sem apressar), exceto o módulo GPU Nvidia, que não possui documentação clara. (Ainda estou preso )

Para instalar os gânglios, você pode fazer o seguinte. No servidor:

sudo apt-get install -y ganglia-monitor rrdtool gmetad ganglia-webfrontend

Escolha Yes cada vez que você estiver fazendo uma pergunta sobre o Apache

Primeiro,configuramososervidorGanglia,porexemplo,gmetad:

sudocp/etc/ganglia-webfrontend/apache.conf/etc/apache2/sites-enabled/ganglia.confsudonano/etc/ganglia/gmetad.conf

Emgmetad.conf,façaasseguintesalterações:

Substituir:

data_source"my cluster" localhost

por (assumindo que 192.168.10.22 é o IP do servidor)

data_source "my cluster" 50 192.168.10.22:8649

Isso significa que o Ganglia deve escutar na porta 8649 (que é a porta padrão do Ganglia). Você deve se certificar de que o IP e a porta estejam acessíveis para os clientes do Ganglia que serão executados nas máquinas que você planeja monitorar.

Você agora pode iniciar o servidor Ganglia:

sudo /etc/init.d/gmetad restart
sudo /etc/init.d/apache2 restart

Você pode acessar a interface da web no link (onde 192.168.10.22 é o IP do servidor)

Segundo , configuramos o cliente do Ganglia (por exemplo, gmond ), na mesma máquina ou em outra máquina.

sudo apt-get install -y ganglia-monitor

sudo nano /etc/ganglia/gmond.conf

Em gmond.conf , faça as seguintes alterações para que o cliente do Ganglia, por exemplo, gmond , aponte para o servidor:

Substituir:

cluster {
name = "unspecified"
owner = "unspecified"
latlong = "unspecified"
url = "unspecified"
}

para

cluster {
name = "my cluster"
owner = "unspecified"
latlong = "unspecified"
url = "unspecified"
}

Substituir

udp_send_channel {
mcast_join = 239.2.11.71
port = 8649
ttl = 1
}

por

udp_send_channel {
# mcast_join = 239.2.11.71
host = 192.168.10.22
port = 8649
ttl = 1
}

Substituir:

udp_recv_channel {
mcast_join = 239.2.11.71
port = 8649
bind = 239.2.11.71
}

para

udp_recv_channel {
# mcast_join = 239.2.11.71
port = 8649
# bind = 239.2.11.71
}

Agora você pode iniciar o cliente do Ganglia:

sudo /etc/init.d/ganglia-monitor restart

Ele deve aparecer dentro de 30 segundos na interface da Web do Ganglia no servidor (por exemplo, link ).

Como o arquivo gmond.conf é o mesmo para todos os clientes, você pode adicionar o monitoramento de ganglia em uma nova máquina em alguns segundos:

sudo apt-get install -y ganglia-monitor
wget http://somewebsite/gmond.conf # this gmond.conf is configured so that it points to the right ganglia server, as described above
sudo cp -f gmond.conf /etc/ganglia/gmond.conf
sudo /etc/init.d/ganglia-monitor restart

Eu usei os seguintes guias:

Um script bash para iniciar ou reiniciar gmond em todos os servidores que você deseja monitorar:

deploy.sh :

#!/usr/bin/env bash

# Some useful resources:
# while read ip user pass; do : http://unix.stackexchange.com/questions/92664/how-to-deploy-programs-on-multiple-machines
# -o StrictHostKeyChecking=no: https://sobrelinux.info/questions/92656/regarding-host-key-verification-failed"$pass" ssh $user@$ip  -o StrictHostKeyChecking=no -T "
  echo $pass | sudo -S sudo /etc/init.d/ganglia-monitor restart
  "
  echo 'done'
done 3<servers.txt

servers.txt :

53.12.45.74 my_username my_password
54.12.45.74 my_username my_password
57.12.45.74 my_username my_password
‌‌ 

Capturas de tela da página principal na interface da Web:

O

link oferece uma boa visão geral da interface da Web do Ganglia:

    
por 21.04.2016 / 16:10
0

Como disse , eu poderia escrever minha própria ferramenta, então aqui está (não polida, mas funciona.):

Lado do cliente (ou seja, o nó da GPU)

gpu_monitoring.sh (assume que o IP do servidor que serve a página da Web de monitoramento é 128.52.200.39 )

while true; 
do 
    nvidia-smi --query-gpu=utilization.gpu,utilization.memory,memory.total,memory.free,memory.used --format=csv >> gpu_utilization.log; 
    python gpu_monitoring.py
    sshpass -p 'my_password' scp -o StrictHostKeyChecking=no ./gpu_utilization_100.png [email protected]:/var/www/html/gpu_utilization_100_server1.png
    sshpass -p 'my_password' scp -o StrictHostKeyChecking=no ./gpu_utilization_10000.png [email protected]:/var/www/html/gpu_utilization_10000_server1.png
    sleep 10; 
done

gpu_monitoring.py :

'''
Monitor GPU use
'''

from __future__ import print_function
from __future__ import division

import numpy as np

import matplotlib
import os
matplotlib.use('Agg') # http://stackoverflow.com/questions/2801882/generating-a-png-with-matplotlib-when-display-is-undefined
import matplotlib.pyplot as plt
import time
import datetime




def get_current_milliseconds():
    '''
    http://stackoverflow.com/questions/5998245/get-current-time-in-milliseconds-in-python
    '''
    return(int(round(time.time() * 1000)))


def get_current_time_in_seconds():
    '''
    http://stackoverflow.com/questions/415511/how-to-get-current-time-in-python
    '''
    return(time.strftime("%Y-%m-%d_%H-%M-%S", time.gmtime()))

def get_current_time_in_miliseconds():
    '''
    http://stackoverflow.com/questions/5998245/get-current-time-in-milliseconds-in-python
    '''
    return(get_current_time_in_seconds() + '-' + str(datetime.datetime.now().microsecond))




def generate_plot(gpu_log_filepath, max_history_size, graph_filepath):
    '''

    '''
    # Get data
    history_size = 0
    number_of_gpus = -1
    gpu_utilization = []
    gpu_utilization_one_timestep = []
    for line_number, line in enumerate(reversed(open(gpu_log_filepath).readlines())): # http://stackoverflow.com/questions/2301789/read-a-file-in-reverse-order-using-python
        if history_size > max_history_size: break
        line = line.split(',')

        if line[0].startswith('util') or len(gpu_utilization_one_timestep) == number_of_gpus:
            if number_of_gpus == -1 and len(gpu_utilization_one_timestep) > 0:
                 number_of_gpus = len(gpu_utilization_one_timestep)
            if len(gpu_utilization_one_timestep) == number_of_gpus:
                gpu_utilization.append(list(reversed(gpu_utilization_one_timestep))) # reversed because since we read the log file from button to up, GPU order is reversed.
                #print('gpu_utilization_one_timestep: {0}'.format(gpu_utilization_one_timestep))
                history_size += 1

            else: #len(gpu_utilization_one_timestep) <> number_of_gpus:
                pass
                #print('gpu_utilization_one_timestep: {0}'.format(gpu_utilization_one_timestep))

            gpu_utilization_one_timestep = []

        if line[0].startswith('util'): continue

        try:
            current_gpu_utilization = int(line[0].strip().replace(' %', ''))
        except:
            print('line: {0}'.format(line))
            print('line_number: {0}'.format(line_number))
            1/0
        gpu_utilization_one_timestep.append(current_gpu_utilization)

    # Plot graph
    #print('gpu_utilization: {0}'.format(gpu_utilization))
    gpu_utilization = np.array(list(reversed(gpu_utilization))) # We read the log backward, i.e., ante-chronological. We reverse again to get the chronological order.

    #print('gpu_utilization.shape: {0}'.format(gpu_utilization.shape))
    fig = plt.figure(1)
    ax = fig.add_subplot(111)
    ax.plot(range(gpu_utilization.shape[0]), gpu_utilization)
    ax.set_title('GPU utilization over time ({0})'.format(get_current_time_in_miliseconds()))
    ax.set_xlabel('Time')
    ax.set_ylabel('GPU utilization (%)')
    gpu_utilization_mean_per_gpu = np.mean(gpu_utilization, axis=0)
    lgd = ax.legend( [ 'GPU {0} (avg {1})'.format(gpu_number, np.round(gpu_utilization_mean, 1)) for gpu_number, gpu_utilization_mean in zip(range(gpu_utilization.shape[1]), gpu_utilization_mean_per_gpu)]
                     , loc='center right', bbox_to_anchor=(1.45, 0.5))
    plt.savefig(graph_filepath, dpi=300, format='png', bbox_inches='tight')
    plt.close()



def main():
    '''
    This is the main function
    '''
    # Parameters
    gpu_log_filepath = 'gpu_utilization.log' 
    max_history_size = 100

    max_history_sizes =[100, 10000] 
    for max_history_size in max_history_sizes:
        graph_filepath = 'gpu_utillization_{0}.png'.format(max_history_size)
        generate_plot(gpu_log_filepath, max_history_size, graph_filepath)


if __name__ == "__main__":
    main()
    #cProfile.run('main()') # if you want to do some profiling

Lado do servidor (ou seja, o servidor da Web)

gpu.html :

<!DOCTYPE html>
<html>
<body>


<h2>gpu_utilization_server1.png</h2>
<img src="gpu_utilization_100_server1.png" alt="Mountain View" style="height:508px;"><img src="gpu_utilization_10000_server1.png" alt="Mountain View" style="height:508px;">


</body>
</html>
    
por 24.04.2016 / 05:11
0

Ou simplesmente use

link

, que age exatamente da mesma maneira que nvidia-smi no terminal, mas reúne todas as informações dos nós em todo o cluster, que estão executando o cluster-smi-node . A saída será

+---------+------------------------+---------------------+----------+----------+
| Node    | Gpu                    | Memory-Usage        | Mem-Util | GPU-Util |
+---------+------------------------+---------------------+----------+----------+
| node-00 | 0: TITAN Xp            |  3857MiB / 12189MiB | 31%      | 0%       |
|         | 1: TITAN Xp            | 11689MiB / 12189MiB | 95%      | 0%       |
|         | 2: TITAN Xp            | 10787MiB / 12189MiB | 88%      | 0%       |
|         | 3: TITAN Xp            | 10965MiB / 12189MiB | 89%      | 100%     |
+---------+------------------------+---------------------+----------+----------+
| node-01 | 0: TITAN Xp            | 11667MiB / 12189MiB | 95%      | 100%     |
|         | 1: TITAN Xp            | 11667MiB / 12189MiB | 95%      | 96%      |
|         | 2: TITAN Xp            |  8497MiB / 12189MiB | 69%      | 100%     |
|         | 3: TITAN Xp            |  8499MiB / 12189MiB | 69%      | 98%      |
+---------+------------------------+---------------------+----------+----------+
| node-02 | 0: GeForce GTX 1080 Ti |  1447MiB / 11172MiB | 12%      | 8%       |
|         | 1: GeForce GTX 1080 Ti |  1453MiB / 11172MiB | 13%      | 99%      |
|         | 2: GeForce GTX 1080 Ti |  1673MiB / 11172MiB | 14%      | 0%       |
|         | 3: GeForce GTX 1080 Ti |  6812MiB / 11172MiB | 60%      | 36%      |
+---------+------------------------+---------------------+----------+----------+

ao usar 3 nós.

Ele usa NVML para ler esses valores diretamente por eficiência. Sugiro que não analise a saída de nvidia-smi como proposto nas outras respostas. Além disso, você pode rastrear essas informações em cluster-smi usando Python + ZMQ.

    
por 14.12.2017 / 18:52