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