Optimización comunicaciones

De i2basque

Contenido

Optimización de las comunicaciones para cálculo intensivo

Las opciones utilizadas por los sistemas operativos en las comunicaciones son por defecto opciones conservadoras para asegurar su funcionamiento correcto con la mayor variedad de configuraciones y sistemas.

Es posible una rápida optimización de estos valores para alcanzar un mayor rendimiento en las comunicaciones. Para ello es necesaria una evaluación del rendimiento actual y una optimización de los valores actuales en varios apartados.


Evaluación del rendimiento actual

Existen diversas herramientas para la evaluación del rendimiento de las comunicaciones entre sistemas interconectados por una red. Una lista de los más utilizados se encuentra en TCP Tuning.

Para el sistema GRID de i2BASQUE hemos utilizado Iperf. Su funcionamiento básico es muy sencillo. En este ejemplo medimos la velocidad de las comunicaciones TCP usando el tamaño de las ventanas por defecto entre dos nodos adyacentes en el cluster de Vitoria.

vit1:~# iperf -s 
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size:   256 KByte (default)
------------------------------------------------------------
[  4] local 10.0.2.2 port 5001 connected with 10.0.2.3 port 40651
[  4]  0.0-10.0 sec  1.09 GBytes    938 Mbits/sec
vit2:~# iperf -c vit1
------------------------------------------------------------
Client connecting to vit1, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  3] local 10.0.2.3 port 40651 connected with 10.0.2.2 port 5001
[  3]  0.0-10.0 sec  1.09 GBytes    938 Mbits/sec

En este ejemplo el nodo vit1 del cluster de Vitoria hace de servidor, y el nodo vit2 se conecta a él para realizar la medición. Como se puede observar el rendimiento del enlace es de 938Mbps. Es un buen resultado, teniendo en cuenta que el enlace es de Gigabit ethernet, y hay algunas aplicaciones que usan la red en el momento de realizar la prueba. Antes de la prueba se han realizado las optimizaciones apropiadas.

Optimización de los parámetros de TCP/IP

Hay diversas guías y artículos dedicados al estudio de la optimización de los parámetros de TCP/IP y de los algoritmos de control de congestión. Recomendamos las siguientes referencias:

El principal problema con TCP es escoger el tamaño óptimo de la ventana de emisión, que teóricamente es:

tamaño ventana = 2 * ancho de banda * retraso (o delay)

El programa ping proporciona el tiempo de ida y vuelta (RTT o Round Trip Time). Podemos usar su resultado directamente en la fórmula anterior:

tamaño ventana = ancho de banda * RTT

En nuestro caso podemos sustituir:

tamaño de ventana = 1Gbps * 0,318ms = 125000KBps * 0,318e-3s = 39,75KB

Una vez obtenido este dato podemos hacer pruebas con distintos tamaños de buferes con el comando Iperf:

vit1:~# iperf -s -w 39.75k                                                    
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 79.5 KByte (WARNING: requested 39.8 KByte)
------------------------------------------------------------
[  4] local 10.0.2.2 port 5001 connected with 10.0.2.3 port 40696
[  4]  0.0-10.0 sec    972 MBytes    816 Mbits/sec

vit2:~# iperf -c vit1 -w 39.75k
------------------------------------------------------------
Client connecting to vit1, TCP port 5001
TCP window size: 79.5 KByte (WARNING: requested 39.8 KByte)
------------------------------------------------------------
[  3] local 10.0.2.3 port 40696 connected with 10.0.2.2 port 5001
[  3]  0.0-10.0 sec    972 MBytes    816 Mbits/sec
  • Nota: El parámetro -w es para especificar el tamaño de la ventana TCP.

Como se puede observar los valores obtenidos con este valor distan mucho de los óptimos. Hay que probar con muchos valores hasta dar con los óptimos.

También podemos modificar más parámetros aparte de los de la ventana TCP. Hay un índice de los distintios valores de los parámetros de TCP en Linux haciendo man 7 tcp o en Linux man page for TCP(7). Podemos seguir también varias guías para optimizar los valores de TCP como TCP Tuning Guide que es para Linux pero desde ahí también se puede acceder a otros sistemas operativos.

Los valores que hemos modificado están en el fichero de configuración /etc/sysctl.conf:

vit1:~# more /etc/sysctl.conf
#
# /etc/sysctl.conf - Configuration file for setting system variables
# See sysctl.conf (5) for information.
#
# Be warned that /etc/init.d/procps is executed to set the following
# variables.  However, after that, /etc/init.d/networking sets some
# network options with builtin values.  These values may be overridden
# using /etc/network/options.

#kernel.domainname = example.com
#net/ipv4/icmp_echo_ignore_broadcasts=1
# increase TCP max buffer size
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# increase Linux autotuning TCP buffer limits
# min, default, and max number of bytes to use
#mejor entre distintos clusters iperf 902 112
#net.ipv4.tcp_rmem = 4096 87380 16777216 
#net.ipv4.tcp_wmem = 4096 65536 16777216
#mejor entre mismo cluster 942 27
net.ipv4.tcp_rmem = 4096 262144 16777216 
net.ipv4.tcp_wmem = 4096 16384 16777216
# don't cache ssthresh from previous connection
net.ipv4.tcp_no_metrics_save = 1
# recommended to increase this for 1000 BT or higher
net.core.netdev_max_backlog = 2500 

Para poner estos valores en producción se usa la herramienta sysctl, usando el comando sysctl -p.

Como podemos ver en el fichero de configuración anterior, los valores net.core.rmem_max y net.core.wmem_max corresponden a los tamaños máximos de las ventanas TCP.

  • Nota: Linux dobla el tamaño del buffer pedido. Así que lo que hemos puesto arriba significa que el máximo tamaño de la ventana TCP será de 32MB.

Los valores net.ipv4.tcp_rmem y net.ipv4.tcp_wmem corresponden a los valores mínimo, por defecto y máximo de las ventanas de TCP que se irán ajustando según los algoritmos de control de congestión que se vayan usando como:

  • reno: TCP tradicional que se usa en la mayoría de sistemas operativos. (por defecto)
  • bic: BIC-TCP
  • highspeed: HighSpeed TCP: algoritmo sugerido por Sally Floyd
  • htcp: Hamilton TCP
  • hybla: Para enlaces de satélite
  • scalable: TCP escalable
  • vegas: TCP Vegas
  • westwood: optimizado para redes con pérdidas frecuentes de paquetes

También se ha puesto el valor net.ipv4.tcp_no_metrics_save = 1 que sirve para que no se cacheen los datos de las métricas de las rutas para cada conexión, valores tales como RTT o cwnd, etc.

El valor net.core.netdev_max_backlog = 2500 significa que como máximo se procesarán 2500 paquetes de los que hay pendientes en la cola de recepción de la tarjeta ethernet cuando llegue la interrupción de que acaba de llegar un paquete de la red. El valor por defecto de este atributo en la mayoría de las tarjetas de red es 300 y sólo debería ser modificado para tarjetas Gigabit (como las nuestras) o 10Gigabit poniendo el valor 30000. Un valor demasiado grande o pequeño de este atributo puede tener consecuencias nefastas en el rendimiento.

Optimización de los parámetros del driver de las tarjetas ethernet TCP/IP

Asímismo se pueden manipular varios parámetros del driver de la tarjeta de red para aumentar el rendimiento. Para linux la base de la documentación sobre drivers de tarjetas de red está en Linux Network Drivers & Networking Utilities.

Para nuestras tarjetas de red Intel Gigabit PRO/1000MT los parámetros que pueden ser configurados pueden observarse en Networking and Communications: Advanced Settings Help File for Intel® Adapters. En linux los parámetros que se pueden cambiar están disponibles en Networking and Communications: Linux* Base Driver.

En cuanto a la optimización del driver se pueden hacer dos aproximaciones distintas, una más enfocada a la disminución del gasto de CPU en cada nodo, y otra enfocada a aumentar el rendimiento de la red bajando la latencia. Nostros hemos optado por la segunda, ya que la latencia es el principal problema entre el rendimiento de redes tipo ethernet de propósito general mucho más caras en contra de redes específicamente disañadas para cálculo científico tipo MPI, como por ejemplo Myrinet que son mucho más caras. La primera opción es más adecuada en aquellos clusters que vayan a ejecutar un único proceso por nodo que consuma toda la CPU y que tenga muy poca comunicación con otros nodos del mismo cluster. En nuestro caso nuestros clusters están pricipalmente dedicados a la ejecución de aplicaciones paralelas tipo MPI con mucha comunicación entre ellas, y lo que se ha pretendido es bajar al máximo la latencia de los mensajes para así acortar la distancia de rendimiento que separa nuestra red tipo Ethernet con Myrinet.

En cuanto a nuestro entorno se refiere hemos estado realizando numerosas pruebas y los parámetros que mas nos han convenido son los que se enumeran en el fichero /etc/modules.conf relativos a la tarjeta de red (Sólo se pone el extracto relativo a la tarjeta de red):

options e1000 InterruptThrottleRate=0 RxIntDelay=0 TxIntDelay=0 RxAbsIntDelay=0 TxAbsIntDelay=0

Las opciones que se le pasan al driver e1000 quieren decir en orden relativo:

  • InterruptThrottleRate=0: Representa el máximo número de interrupciones por segundo que genera el controlador de la tarjeta de red. Al ponerlo a 0 se desactiva, quiere decir que genera una por trama que se reciba de la red, las que hagan falta. Esto consume más procesador, ya que cada interrupción hace que la CPU tenga que ejecutar una rutina de interrupción, pero hará que cada trama llegue a su destino lo antes posible minimizando así la latencia de la red.
  • RxIntDelay=0: Este valor retrasa la recepción de interrupciones en unidades de 1024 microsegundos. La reducción de la recepción de las interrupciones puede mejorar si se configura apropiadamente para un específico tráfico de red. El aumento de este valor añade latencia extra a la recepción de tramas y puede acabar en un decrecimiento del rendimiento del tráfico TCP. Si el sistema informa de que hay recepcciones que son descartadas, este valor puede ser demasiado alto, y causar que el driver se quede sin memoria para recibir más tramas. Al ponerlo a 0 hacemos que la llegada de cada trama suponga una interrupción y se entregue inmediatamente haciendo que se consuma más CPU, pero disminuyendo la latencia.
  • TxIntDelay=0: Este valor retrasa la generación de interrupciones en unidades de 1024 microsegundos. La reducción de las interrupciones de transmisión puede mejorar el consumo de CPU si se configura apropiadamente para un específico tráfico de red. Si el sistema informa de que hay transmisiones que son descartadas, este valor puede ser demasiado alto, y causar que el driver se quede sin memoria para poder encolar más tramas a enviar. Al ponerlo a 0 hacemos que la transmisión de cada trama suponga una interrupción y se envíe inmediatamente haciendo que se consuma más CPU, pero disminuyendo la latencia.
  • RxAbsIntDelay=0: Este valor viene como los anteriores en unidades de 1024 microsegundos. Limita el retraso con el que se genera una interrupción. Útil sólo cuando RxIntDelay es distinto de 0, asegura que una interrupción es generada en la cantidad de tiempo indicada después de la llegada de la primera trama. Al ponerlo a 0 indica que las tramas se entreguen lo antes posible.
  • TxAbsIntDelay=0: Este valor viene como los anteriores en unidades de 1024 microsegundos. Limita el retraso con el que se genera una interrupción. Útil sólo cuando TxIntDelay es distinto de 0, asegura que una interrupción es generada en la cantidad de tiempo indicada después del envío de la primera trama por el cable. Al ponerlo a 0 indica que las tramas se manden lo antes posible.

También podemos aumentar la cola de envío de mensajes de la interfaz de red, que nos hará ganar algo de rendimiento, sobre todo en tarjetas tipo gigabit, en las que el parámetro por defecto está a 1000. Esto se consigue con el comando ifconfig:

ifconfig eth0 txqueuelen 10000 

Por último indicar que otra optimización realizada es la indicada en TCP Tuning Guide y que se refiere a un bug que hay en algunos drivers de red integrados en el núcleo de linux en verisones anteriores a la 2.6.12, y que tiene que ver con la descarga de hacer la segmentación de paquetes al núcleo. Para ello hay que hacer:

ethtool -K eth0 tso off


Volver a Manual GRID de i2BASQUE

Herramientas personales
Otros idiomas