Detection and Containment Amortization UDP Sockets for

Transcripción

Detection and Containment Amortization UDP Sockets for
Detection and Containment Amortization UDP
Sockets for Multithreading on Multicore
Machines
S. Blasco, J. Bustos and D. Rivera
1
Abstract— The use of parallelism has become the first choice
when seeking better efficiency in the implementation and
execution of tasks. However, there are cases where not achieve
real gains with this technique, for example the case of concurrent
access and read access on UDP sockets on Linux. This paper
presents profiling and testing techniques in Linux to show how
UDP sockets have points of contention inherent in its design,
resources that make them incompatible with the traditional
parallelism schemes that provide access to a shared structure,
and checks how finally the problem is transferred to the
communication layer between different processors with real cost.
Finally, a simple and novel approach is presented to provide
efficiency in the context specified without penalize the
communication channels between processors.
responsabilidad de éste mal comportamiento a los
componentes de sincronización presentes en los niveles más
bajos de la implementación de las estructuras sockets en Linux
como son los spinlocks, cuya responsabilidad es precisamente
brindar exclusión mutua en el acceso a dicha estructura. De
esta manera, algunos trabajos postulan que sería el spinlock un
candidato de responsabilidad en la formación de un punto de
contención de recursos al momento de añadir lecturas
paralelas.
Keywords— contention, multithreading, paralelism, multicore,
PMU, Intel Quickpath, NUMA, performance counters.
D
I. INTRODUCCIÓN
ESDE el surgimiento de los sistemas con múltiples
procesadores, la tendencia ha sido aprovechar el
procesamiento paralelo en pos de alcanzar mejores tiempos de
ejecución. Para ello, una técnica muy usada es la
programación multi-hilo, que permite paralelizar la ejecución
de cada hilo cuando se tienen tareas independientes entre sí.
Este fenómeno es posible, entre otras razones, porque los
sistemas operativos modernos han desarrollado sofisticados
mecanismos de scheduling, permitiendo una distribución de
hilos en ejecución como tareas que se procesan en diferentes
núcleos (Tanto físicos como lógicos) de procesamiento,
dotando a cada hilo de núcleos de procesamiento reales para
ejecutar sus instrucciones, brindando así ganancias efectivas
en tiempos de trabajo.
A pesar de lo anterior, el escalamiento en la velocidad de
procesamiento de una tarea no es siempre una tarea posible
usando dichas técnicas, en que al incorporar éste enfoque,
lejos de obtener ganancias de tiempo de ejecución, se termina
por degradar sistemas completos.
A. El Problema
Un ejemplo de ello es el caso de los sockets UDP en
entornos multi-CPU. Se ha verificado que al incorporar
procesamiento concurrente con múltiples hilos en el consumo
de dato desde un único socket UDP, se genera una
degradación en la tasa de consumo de datos [1, 2]. Otros
trabajos en la misma línea se han limitado a atribuir la
1
S. Blasco, NIC Chile Research Labs, Chile, [email protected]
J. Bustos, NIC Chile Research Labs, Chile, [email protected]
D. Rivera, SAMOVAR, Télécom SudParis, CNRS, Université ParisSaclay, France, [email protected]
1
Figura 1. Esquema del caso problemático estudiado, donde al consumir datos
desde un socket UDP sobrecargado, usando múltiples hilos, se termina por
degradar el rendimiento general. El esquema postula como problema un punto
de contención en el acceso al socket que se traduce en problemas de
comunicación entre los procesadores del sistema.
Esta situación degenera en muchos otros problemas como
fenómenos de cuello de botella, problemas de rebotes y
coordinación de caché y problemas de distribución de carga
que podrían acrecentarse a medida que el escenario
concurrente se vuelve más agresivo [4]. Sin embargo, el
anterior es un diagnostico que, siendo plenamente razonable
en términos teóricos, no ha sido cuantificado
experimentalmente en la práctica.
B. Objetivos
El objetivo de este trabajo es proponer un método para la
verificación en la contención de recursos a nivel de hardware
utilizando componentes de los procesadores modernos,
además de ofrecer una propuesta de solución para lograr un
mejor rendimiento en el uso de sockets UDP en múltiples
arquitecturas de CPU.
II. MÉTODO Y VERIFICACIÓN EXPERIMENTAL
Para demostrar experimentalmente el problema como un
escenario de uso excesivo de comunicación entre
componentes de hardware de un sistema, se pueden emplear
distintas herramientas de análisis basadas en el monitoreo de
la Performance Monitoring Unit (PMU) asociado a los
sistemas modernos, para así rescatar estadísticas de los
Performance Counters registrados. Dichos Performance
Counters permiten cuantificar distintas operaciones de bajo
nivel del sistema, como por ejemplo: Lecturas de caché en
distintos niveles de acceso, modificaciones de estado en líneas
de memoria, actualización de valores por razón de protocolos
de coordinación como MESI y SNOOP [8, 9], etc.
En la práctica, la lectura de los Performance Counters se
puede realizar usando software de profiling especializado.
Existen diversas alternativas para éste propósito, siendo las
más populares Perf(https://perf.wiki.kernel.org), PAPI
(http://icl.cs.utk.edu/papi)
y
HPCTOOLKIT
(http://hpctoolkit.org) [6] por mencionar algunas.
A. Especificación de Hardware
Pera el análisis anterior, es necesario limitar el entorno
experimental a evaluar, ello pues los distintos fabricantes de
procesadores hacen distintas implementaciones en sus equipos
para monitorear eventos. El presente estudio se basa en la
evaluación experimental sobre un equipo de las características
de la Fig. 2.
Figura 2. Diagrama generado con la utilidad lstopo que ilustra la
infraestructura interna del sistema evaluado. Corresponde a un servidor
dotado de dos nodos NUMA, cada uno con un procesador Intel® Xeon® CPU
X5660 @ 2.80GHz de 6 núcleos con tecnología hyperthreading, dando un
total de 24 núcleos lógicos en el sistema. Con respecto al software, el sistema
ejecuta CentOS 6.5 con un Linux kernel 2.6.32431.el6.x86_64;
De acuerdo con las especificaciones del fabricante [3] para
el hardware estudiado, se puede delimitar una colección de
eventos relacionados a la operación de la Intel® QuickPath®
Architecture [5], que comprende a la tecnología de Intel usada
en los canales de comunicación entre los distintos núcleos en
cada conjunto de procesadores del sistema. Dichos canales
corresponden a un punto de paso de datos crucial en nuestro
experimento pues en aplicaciones multi-hilo --como nuestro
caso de estudio-- estos puntos son nuestros candidatos de
sobrecarga, explicado por el alto grado de coordinación que se
requiere entre los procesadores en éstos casos. Por su
naturaleza, el comportamiento de los eventos registrados en
éste punto debe tener estrecha relación con el ritmo de
consumo de datos de nuestro experimento.
Nuestra hipótesis plantea que existe un conjunto acotado de
eventos que se ven impactados por efecto del recurso
compartido, el objeto de la contención. De la misma manera,
se espera que el comportamiento del registro de los eventos
varíe en proporción a los hilos que consumen
concurrentemente un socket. La tabla 1 incluye un grupo de
eventos que implican un costo en el tiempo, en relación a las
sospechas planteadas.
B. El Experimento
Para cada evento involucrado, se estudió el número de
señales generadas mientras se aumentó el número de hilos
consumiendo concurrentemente un mismo socket UDP. El
software usado en la inspección de la prueba fue la
herramienta de captura Perf. De esta manera, el muestreo para
cada evento se almacena como un registro cuantitativo de la
cantidad de llamadas del evento para una determinada
configuración de hilos, de la siguiente manera:
,
, , , , ,
,
,
,
,
(1)
corresponde a una tupla que almacena los
Cada
registros de las distintas evaluaciones para una determinada
configuración de hilos. Los indices representan un evento
puntual de la tabla 1 y los índices indican la configuración de
hilos evaluados en dicha prueba. Cada , es el promedio
luego de 60 repeticiones experimentales de cada prueba.
TABLA I
EVENTOS TOTALES RECOGIDOS EN LA EVALUACIÓN DE
DIFERENTES HILOS QUE CONSUMEN UN MISMO SOCKET UDP
QPI/GQ/CACHE
LinkLayer
UNC_GQ_DATA_FROM SNOOPQ_REQUESTS
UNC_GQ_DATA_TO
SNOOPQ_REQUESTS_OUTSTANDING
UNC_QHL_REQUESTS
SNOOP_RESPONSE
L1D
UNC_QPI_RX_NO_PPT_CREDIT
L2_DATA_RQSTS
UNC_QPI_TX_STALLED_MULTI_FLIT
UNC_LLC_HITS
UNC_QPI_TX_STALLED_SINGLE_FLIT
UNC_LLC_MISS
UNC_SNP_RESP_TO_LOCAL_HOME
UNC_LLC_LINES_IN
UNC_SNP_RESP_TO_REMOTE_HOME
UNC_LLC_LINES_OUT
UNC_IMC_RETRY
TABLA I: EVENTOS TOTALES RECOGIDOS EN LA EVALUACIÓN DE
DIFERENTES HILOS QUE CONSUMEN UN MISMO SOCKET UDP. Los
eventos se dividen en dos grupos: QPI/GQ/CACHE relacionados con el
movimiento de datos entre diferentes estructuras para comunicación según la
especificación de hardware, y LinkLayer para los eventos que se refiere a la
sincronización de los protocolos de coherencia y capa de corrección de errores
que se activan en escenarios de rebotes de cache.
C. Resultados
A partir de los resultados de la Fig. 3, se ilustran dos
tendencias principales: La primera tendencia dada por los
registros r500205 y r500404 que muestran cómo, cuándo se
alcanza el límite de 24 hilos, los valores contados aumentan
explosivamente. Este es un comportamiento plenamente
razonable dado que 24 es el límite de núcleos de
procesamiento disponibles en el sistema, luego, al sobrepasar
éste número de hilos, es esperable que el sistema entre de
lleno en labores de cambios de contexto y sobrecarga.
La segunda tendencia es la ilustrada por los resultados de
los eventos r500204 y r530851, que muestran como los
registros aumentan en un valor significativo con cada
incremento de hilos en el consumo, lo que se traduce en
mayores costos sobre los canales de comunicación con
respecto a la primera tendencia. En éste caso, el incremento de
contadores no se explica por una sobrecarga del sistema, sino
más bien revela un sobreuso de las operaciones como son:
coordinación de cachés, actualización de valores de memoria,
etc.
Para visualizar mejor las tendencias, se construyó una
matriz de correlación con el conjunto de eventos
seleccionados para verificar la relación entre las dos
tendencias antes mostradas. En efecto, una amplia mayoría de
los eventos registrados presentan un muy alto índice de
correlación que se ajusta a la tendencia expresada por registros
como r530851, que muestra un significativo aumento al
incorporar más y más hilos sin indicios de sobrecarga, lo cual
corrobora la sospecha de un fenómeno de contención de
recursos a nivel de los canales de comunicación de hardware.
Figura 3. Resultados del registro de 4 eventos que revelan cómo el grado de
comunicación producida entre componentes del sistema se incrementa en dos
tendencias a medida que se van agregando más hilos.
Figura 4. Matriz de correlación que muestra las tendencias de los
acontecimientos, ya que incorporan más hilos que consumen socket UDP,
generado con el software Statgraphics (http://www.statgraphics.com/).
compartiendo así la interfaz y delegando el trabajo de la
distribución de paquetes (siempre equitativa) al kernel. En la
práctica, esta opción mejora el rendimiento aprovechando real
tomando ventaja del paralelismo en el consumo de datos,
utilizando múltiples sockets UDP para llegar a un mejor
rendimiento.
A pesar de tener un buen desempeño, la propuesta anterior
presenta algunos problemas como el no ser perfectamente
estándar entre distribuciones de Linux, además de tener una
pobre documentación técnica. Reuseport añade otro problema:
Para que funcione, el primer socket que se enlace al puerto
deseado debe disponer la opción de sistema SO_REUSEPORT
habilitada y, sólo desde ese momento, las nuevas conexiones
se pueden acoplar en el mismo puerto. Esta etapa de
configuración inicial, además de romper uno de los principios
básicos de la programación de la red (la paridad 1 a 1 puerto
de socket), obliga a modificar las aplicaciones desde su lógica
de programación, esto al necesitar incorporar más ajustes al
momento de iniciar las conexiones.
Otra buena técnica para tomar ventaja de paralelismo de
esta misma manera sería el uso de IPTables para, inspirados
en la dinámica de Reuseport, crear reglas que permitan la
distribución de paquetes a distintos puertos, y delegar el
consumo de datos a diferentes tareas en diferentes sockets
UDP. En la práctica, este enfoque funciona, pero la
configuración IPTables es comúnmente una tarea difícil y
compleja.
B. Nuestra Propuesta
Se propone el diseño de un componente de sistema
modular, no invasivo y extensible, que permita aprovechar las
ventajas de reuseport conservando las técnicas de
programación estándar en redes y que genere una ganancia
real en el consumo de datos. Teniendo en cuenta estos
requisitos, se desarrolló como solución ( Disponible en
https://github.com/niclabs/UDPRedistributeModule)
un
módulo del kernel que hiciera uso del framework de Netfilters
disponible en sistemas Linux, a modo de actuar como un
proxy UDP que, interceptando los paquetes entrantes, pudiera
redistribuidos entre un grupo de puertos seleccionados al
momento de instalar el módulo [7].
Con estos resultados se puede establecer que el aumento del
acceso a los sockets UDP utilizando múltiples hilos, degrada
la capacidad de consumir información en ella al llevar a los
distintos canales de comunicación del sistema a un escenario
de alto tráfico, por lo que la mejor alternativa para mejorar el
consumo de datos de éste tipo de estructuras no incorporaría el
acceso simultáneo y se limitaría a utilizar un solo hilo por
socket.
III. LA SOLUCIÓN
A. Soluciones Disponibles
Para superar el bajo rendimiento de los hilos en el acceso
simultáneo a los sockets UDP se han propuesto y desarrollado
diferentes soluciones. Reuseport es una opción desarrollada
por programadores de Google y disponible de Linux a partir
de la versión 3.0 del kernel. Permite que distintas aplicaciones
usen múltiples tomas sobre mismo puerto lógico del sistema,
Figura 5. Diagrama que muestra el esquema propuesto, utilizando el módulo
del kernel diseñado para redistribuir los paquetes UDP entre diferentes
sockets UDP en tareas diferentes. De esta manera, la cantidad de trabajo de
cada socket se reduce y se reduce la comunicación entre tareas en los
diferentes núcleos;
El desarrollo comprende la implementación de dos
esquemas de distribución para los paquetes interceptados:
SequentialSched y RandomSched, para distribuir los
paquetes entre los puertos de redirección configurados al
momento de instalar el módulo de manera secuencial o
aleatoria, respectivamente. La propuesta es modesta, minimal
y eficaz: Como es un módulo del kernel, se instala fácilmente
en cualquier plataforma Linux y es fácilmente modificable
para, por ejemplo, añadir nuevas rutinas de distribución de
paquetes en función del entorno de uso. Además de incorporar
baja sobrecarga al sistema al ejecutarse como un filtro de
Netfilters en el espacio del núcleo.
Figura 7. Esquema conceptual de uso de nuestra solución propuesta,
generalizada para proveer multiplexión de un único puerto, para soportar
múltiples aplicaciones sobre un mismo puerto.
REFERENCIAS
[1]
[2]
[3]
[4]
[5]
Figura 6. Resultados de tiempos en el consumo de un millón de paquetes
usando sockets UDP, empleando los distintos enfoques de solución: Multihilos, reuseport, y el módulo implementado con sus dos variantes de
distribución.
En la práctica, los resultados obtenidos con la propuesta son
perfectamente competitivos en comparación con reuseport,
con la ventaja de que las aplicaciones pueden mantener su
esquema de acción tradicional 1 socket: 1 puerto, sin
necesidad de intervenir el código fuente de las mismas.
Simplemente debiendo atender los puertos que se han
configurado para la redirección de paquetes.
IV. TRABAJO FUTURO
La sencillez de la propuesta hace que sea flexible para
evaluar su desempeño en diferentes escenarios de equilibrio de
carga, permitiendo el uso de múltiples aplicaciones que
consuman de modo conjunto datos desde una misma interfaz
de red lógica. Por otro lado, la propuesta abre la posibilidad de
provechar mejor escenarios de hardware heterogéneos,
persiguiendo mayor eficiencia en el consumo de datos,
pudiendo discriminar en la distribución de paquetes,
delegando su procesamiento a aplicaciones en ejecución sobre
nodos NUMA exclusivos del sistema. En la misma línea, se
pueden aprovechar nuevas posibilidades de intervención de
paquetes para distribuir paquetes a distintas aplicaciones y
procesarlos según corresponda.
Un último enfoque muy interesante radica en el uso de
nuevos y diferentes mecanismos de distribución de paquetes
empleando, por ejemplo, funciones de hash aplicadas sobre las
propiedades de los paquetes mismos. De ésta manera se
vuelve posible un escenario de multiplexación de puerto
lógicos del sistema, permitiendo la comunicación y
administración de comunicación de múltiples servicios a
través de un mismo canal lógico de comunicación.
[6]
[7]
[8]
[9]
D. Rivera, E. Acha, J. Bustos-Jimnez and J. Piquer, Analysis of Linux
UDP Sockets Concurrent Performance. Proceedings of Chilean
Workshop on Distributed Systems and Parallel Computing, 2014.
D. Bueso and S. Norton, An Overview of Kernel Lock Improvements
LinuxConNorth America, Chicago. August 2014.
Intel Corporation, Intel 64 and IA–32 Architectures Software
Developer’s Manual. Combined Volumes:1, 2A, 2B, 2C, 3A, 3B and
3C. 2008.
Tom Herbert, Scaling techniques in the stack for servers with high
connection rates Linux Plumbers Conference: User-visible Network
Issues Mini-Conf, 2010
Intel Corporation, An introduction to the Intel QuickPath Interconnect.
http://www.intel.com/content/dam/doc/white-paper/quick-pathinterconnect-introduction-paper.pdf. Document Number: 320412001US. 2009
Tallent, Mellor-Crummey, HPCToolkit: Performance tools for scientific
computing 2008
Jan Engelhardt, Nicolas Bouliane, Writing Netfilter modules 2012
Papamarcos, M. S., & Patel, J. H. (1984, January). A low-overhead
coherence solution for multiprocessors with private cache memories. In
ACM SIGARCH Computer Architecture News (Vol. 12, No. 3, pp. 348354). ACM.
Ravishanicar, С. V., & Goodman, J. R. (1983). Cache implementation
for multiple microprocessors.
Sebastián Blasco es estudiante de magister en ciencias,
mención computación de la Universidad de Chile. Desde
2013 ha participado como asistente de investigación en
NIC Chile Research Labs (NICLabs). Actualmente se
encuentra completando su tesis de magister en temas de
testing y verificación de la interfaz de red de sistemas
Linux. Sus áreas de interés son dispositivos móviles, Internet y redes.
Diego Rivera es ingeniero civil en computación de la
Universidad de Chile (2013). Desde el 2012 al 2013
trabajó como ayudante de investigación en NIC Chile
Reseach Labs (NICLabs), desarrollando su investigación
en una caracterización del rendimiento en paralelo de los
sockets de Linux. Actualmente se encuentra cursando
PhD en Calidad de Experiencia para servicios Over-TheTop en Télécom SudParis. Sus áreas de interés incluyen
los sistemas distribuidos, sistemas operatvos, calidad de servicio y experiencia
y los modelos de negocios.
Javier Bustos-Jiménez es ingeniero civil en
computación de la Universidad de Chile (2001) y Doctor
en Informática de la Universidad de Niza SophiaAntipolis, Francia (2006). Ha participado en varios
proyectos de innovación, y liderado el proyecto de
construcción de una infraestructura chilena para la
medición de QoS en redes móviles. Es profesor adjunto
en la facultad de ingeniería de la Universidad de Chile desde 2007, y desde
2012 es el director del laboratorio de investigación de NIC Chile (NICLabs).
Es miembro de ACM SIGCOMM y SIGMETRICS y es el USENIX Campus
Reprsentative de la Universidad de Chile

Documentos relacionados