[en] With the end of Moore's Law and Dennard's scaling, attention is shifting to new ways of enhancing computer performance. Improving microprocessor performance is becoming increasingly complex, whereas computational power demands still grow tremendously fast. In recent years, we are witnessing a paradigm change: rather than using one single chip, the CPU, for computing everything, computers are evolving into more heterogeneous organizations. In this new configuration, multiple specialized chips compute specific workloads while the CPU orchestrates them, and is only used for actual computing when no other chip can be used. These specialized chips are usually called accelerators. Since they are highly specialized, architecture enhancements have tremendous room for improvement, unlike CPUs. Accelerators are way more efficient than CPUs in terms of performance, energy consumption, or both. Like multicores, accelerators come with great benefits to computer performance, but also notable challenges to the programming workflow. In environments with multiple accelerators, writing code for each of them is very inefficient since each accelerator is programmed with different languages. Performance is also concerning because programming languages often struggle to exploit hardware to take advantage of its full potential. Lastly, portability is also complicated because when a program is designed for an specific accelerator, it cannot be executed in a different one. Achieving programming languages that provide productivity, performance and portability is known as the P3 problem. To tackle it, in this thesis, we have studied how two different single-source programming languages perform in real-world scenarios. After studying their performance in each of the three P3 categories, we found that they struggle to achieve good performance, portability, and productivity at the same time. Therefore, we have proposed a new domain-specific language specialized in deep neural networks that supports multiple heterogeneous architectures and reaches superior results in all P3 aspects. Even though we can develop programs with decent portability, productivity and performance in heterogeneous environments, there is much code already written. Therefore, if we wish to target new hardware, we would need to rewrite this code with new languages in order to use new accelerators. In this thesis, we propose a compiler that automatically matches and replaces existing code with API calls. Since the target API can be reconfigured easily, our compiler can target an optimized CPU library, which is more efficient than executing the handwritten code or an API that relies on a hardware accelerator. Our proposal is designed for C/C++ and recognizes linear algebra and tensor codes. The main strength of this proposal is its ability to recognize simple code (e.g., the three-loop structure of matrix multiplication) as well as complex code constructs (like the Strassen algorithm, hand-optimized vectorized code, etc.). Furthermore, a notable trend in SoC design, which is becoming increasingly common, is including a sea of disparate accelerators inside the chip. Even though the hardware is already offering performance improvements never seen before, the software is still struggling to take advantage of it. For example, there is no clear way of managing multiple accelerators to accelerate a given workload or how to assign accelerators to the right tasks automatically. Using multiple accelerators concurrently, like how ILP exploits multiple functional units, is called Accelerator-Level Parallelism (ALP). In this thesis, we show a new proposal for exploiting ALP in heterogeneous environments. We present a framework capable of orchestrating multiple accelerators to run a single task jointly, significantly improving performance. We apply our framework to matrix multiplication and convolution use cases, demonstrating that it automatically schedules tasks between accelerators with a low prediction error and a work distribution very close to the optimal. Like multicores did, heterogeneous computing is increasing the complexity of software development and making the architecture of computers more and more complex due to the diverse hardware variety. All computer architecture advances have come with increasing hardware complexity, which we must tame to make computers practical and useful. New architectures, different from the long-lasting CPU, bring unprecedented levels of performance and energy efficiency. In this thesis we have shown that performance portability is possible with singlesource languages, as well as a novel DSL for DNNs that achieves excellent performance, productivity and portability in heterogeneous environments. Also, we have designed a novel methodology for detecting and compiling acceleratable parts of CPU code to specialized hardware accelerators automatically. And lastly, we have proposed a framework for exploiting Accelerator-Level Parallelism in heterogeneous environments. We expect that the proposal described in this thesis will help to improve the usability and the performance of heterogeneous computing, which will relentlessly establish the standard for future-generation computing systems

[es] Después del fin de la ley de Moore y de la escala de Dennard, los arquitectos de computadores han de buscar nuevas formas de mejorar el rendimiento de los computadores. Mejorar el rendimiento de los microprocesadores se está volviendo cada vez más complejo, mientras que las demandas computacionales siguen creciendo tremendamente rápido. En los últimos años estamos presenciando un cambio de paradigma: en vez de usar un único chip, la CPU, para calcular todo, los ordenadores están evolucionando en organizaciones más heterogéneas. En esta nueva configuración, múltiples chips especializados calculan cargas de trabajo específicas mientras que la CPU los orquesta, y solo se usa cuando ningún otro chip puede usarse. A estos chips especializados se les llama a menudo aceleradores. Puesto que están muy especializados, las mejoras en la arquitectura tienen márgenes de mejora enormes, al contrario que las CPU. Los aceleradores son mucho más eficientes que las CPU en términos de rendimiento, consumo energético o ambos. Al igual que los procesadores multinúcleo, los aceleradores traen grandes beneficios al rendimiento de los computadores, pero también grandes retos al flujo de trabajo de los programadores. En entornos con múltiples aceleradores, escribir código para cada uno de ellos es muy ineficiente porque cada acelerador se programa con lenguajes diferentes. El rendimiento también es preocupante, porque los lenguajes de programación suelen tener problemas para explotar el hardware y ser capaz de aprovechar todo su potencial. Por último, la portabilidad también es complicada, porque cuando un programa se diseña para un acelerador en específico, no puede ejecutarse en otro acelerador distinto. Conseguir lenguajes de programación que proporcionen productividad, rendimiento y portabilidad se conoce como el problema de las tres P (P3). Para hacer frente a este problema, en esta tesis hemos estudiado cómo dos lenguajes de programación de código único funcionan en escenarios reales. Después de estudiar su desempeño en cada una de las tres categorías, nos dimos cuenta de que eran incapaces de conseguir un buen rendimiento, portabilidad y productividad al mismo tiempo. Por lo tanto, hemos propuesto un nuevo lenguaje de dominio específico especializado en redes neuronales profundas que soporta diferentes arquitecturas heterogéneos y consigue resultados superiores que los lenguajes estudiados en todos los puntos del problema P3. A pesar de que podemos desarrollar programas con una portabilidad, productividad y rendimiento decentes en entornos heterogéneos, hay mucho código que ya está escrito. Por lo tanto, si quisiéramos utilizar nuevo hardware, necesitaríamos reescribir todo este código con nuevos lenguajes para poder usar aceleradores. En esta tesis proponemos un compilador que detecta y reemplaza código existente con llamadas a librerías de forma automática. Ya que la librería objetivo puede ser reconfigurada fácilmente, nuestro compilador puede llamar a librerías optimizadas para CPU, que es mucho más eficiente que ejecutar el código escrito a mano, o puede llamar a una librería que descansa sobre un acelerador hardware. Nuestra propuesta está diseñada para C/C++ y reconoce programas de álgebra lineal y programas tensoriales. El principal punto fuerte de esta propuesta es su habilidad para reconocer códigos simples (por ejemplo, la estructura de triple bucle de la multiplicación de matrices) así como códigos complejos (como el algoritmo de Strassen, código vectorizado y optimizado a mano, etc). Además, una tendencia relevante en el diseño de los SoC, que está volviéndose cada vez más común, es incluir una gran cantidad de aceleradores diferentes dentro del chip. A pesar de que el hardware ya está ofreciendo mejoras de rendimiento nunca vistas hasta el momento, el software aún es incapaz de aprovecharse de ello. Por ejemplo, no hay ninguna forma evidente de manejar múltiples aceleradores para acelerar una carga de trabajo específica, o cómo asignar aceleradores a las tareas correctas de forma automática. Usar múltiples aceleradores concurrentemente, al igual que el ILP explota usa unidades funcionales, se llama Paralalelismo a Nivel de Acelerador (del inglés, Accelerator Level Parallelism, o ALP). En esta tesis mostramos una nueva propuesta para explotar el ALP en entornos heterogéneos. Presentamos un framework capaz de orquestar múltiples aceleradores para ejecutar una única tarea conjuntamente, mejorando el rendimiento significativamente. Aplicamos nuestro framework a casos de uso de multiplicación de matrices y convolución, demostrando que planifica las tareas entre los aceleradores automáticamente con un error de predicción bajo y con una distribución del trabajo muy cercana a la optima. Al igual que hicieron los procesadores multinúcleo, la computación heterogénea está incrementando la complejidad del desarrollo de software y haciendo la arquitectura de los computadores más y más compleja debido a la diversidad del hardware. Todos los avances en la arquitectura de computadores han venido acompañados de un incremento en la complejidad del hardware, la cual tenemos que domar para hacer los ordenadores prácticos y útiles. Nuevas arquitecturas, diferentes de la CPU, nos traen niveles de rendimiento y eficiencia energética nunca vistos. En esta tesis, hemos mostrado que la performance portability es posible con lenguajes de código único, así como novedosos lenguajes de dominio específico para redes neuronales profundad que consiguen un rendimiento, productividad y portabilidad excelentes en entornos heterogéneos. Además, hemos diseñado una novedosas metodología para detectar y reemplazar partes acelerables de códigos de CPU a aceleradores especializados de forma automática. Y por último, hemos propuesto un framework para explotar el Paralelismo a Nivel de Acelerador en entornos heterogéneos. Esperamos que las propuestas descritas en esta tesis ayuden a mejorar la usabilidad y el rendimiento de la computación heterogénea, que sin duda se convertirá en la norma para los sistemas de computación del futuro.