Título original: Arquitecturas de pegamento y coprocesador.
Autor: Vitalik, fundador de Ethereum. Compilador: Deng Tong, Golden Finance;
Un agradecimiento especial a Justin Drake, Georgios Konstantopoulos, Andrej Karpathy, Michael Gao, Tarun Chitra y varios contribuyentes de Flashbots por sus comentarios y opiniones.
Si analiza con moderado detalle cualquier cálculo que requiera muchos recursos en el mundo moderno, una característica que encontrará una y otra vez es que el cálculo se puede dividir en dos partes:
Una cantidad relativamente pequeña de “lógica empresarial” compleja pero no computacionalmente intensiva;
Mucho “trabajo caro” intensivo pero muy estructurado.
Estas dos formas de computación se manejan mejor de diferentes maneras: la primera, cuya arquitectura puede ser menos eficiente pero debe ser muy general; la segunda, cuya arquitectura puede ser menos general pero debe ser muy eficiente.
¿Cuáles son algunos ejemplos de este enfoque diferente en la práctica?
Primero, veamos el entorno con el que estoy más familiarizado: la máquina virtual Ethereum (EVM). Aquí está el rastro de depuración geth de una transacción reciente de Ethereum que realicé: Actualización del hash IPFS de mi blog en ENS. La transacción consumió un total de 46924 gas y se puede clasificar de la siguiente manera:
Costo base: 21.000
Datos de llamadas: 1.556
Ejecución de EVM: 24.368
Código de operación CARGAR: 6.400
Código de operación SSTORE: 10,100
Código de operación de registro: 2,149
Otros: 6.719
Seguimiento EVM de actualizaciones de hash de ENS. La penúltima columna es el consumo de gas.
La moraleja de la historia es: la mayor parte de la ejecución (alrededor del 73 % si solo se analiza EVM, alrededor del 85 % si se incluye la parte del costo básico que cubre el cálculo) se concentra en un número muy pequeño de operaciones estructuradas costosas: el almacenamiento lee y escritura, registro y cifrado (el costo base incluye 3000 para verificación de firma de pago, EVM también incluye 272 para hash de pago). El resto de la ejecución es "lógica empresarial": intercambiar los bits de datos de llamada para extraer el ID del registro que intento configurar y el hash que lo estoy configurando, etc. En una transferencia de token, esto incluiría sumar y restar saldos; en aplicaciones más avanzadas, esto podría incluir rotaciones, etc.
En EVM, estas dos formas de ejecución se manejan de manera diferente. La lógica empresarial de alto nivel está escrita en un lenguaje de nivel superior, generalmente Solidity, que se compila en EVM. El costoso trabajo todavía se desencadena mediante códigos de operación EVM (SLOAD, etc.), pero más del 99% de los cálculos reales se realizan en módulos dedicados escritos directamente dentro del código del cliente (o incluso bibliotecas).
Para mejorar nuestra comprensión de este patrón, explorémoslo en otro contexto: código de IA escrito en Python usando torch.
Paso hacia adelante de un bloque de modelo de transformador.
¿Qué vemos aquí? Vimos una cantidad relativamente pequeña de "lógica empresarial" escrita en Python, que describe la estructura de las operaciones que se realizan. En una aplicación real, habrá otro tipo de lógica empresarial que determina detalles como cómo obtener la entrada y qué hacer con la salida. Sin embargo, si profundizamos en cada operación individual (los pasos individuales dentro de self.norm, torch.cat, +, *, self.attn...), vemos cálculos vectorizados: las mismas operaciones se calculan masivamente en valores paralelos. . Al igual que en el primer ejemplo, una pequeña parte de los cálculos se utiliza para la lógica empresarial y la mayor parte de los cálculos se utiliza para realizar grandes operaciones matriciales y vectoriales estructuradas; de hecho, la mayoría de ellos son solo multiplicaciones de matrices.
Al igual que en el ejemplo de EVM, estos dos tipos de trabajo se manejan de dos maneras diferentes. El código de lógica empresarial de alto nivel está escrito en Python, un lenguaje muy versátil y flexible, pero también muy lento, y simplemente aceptamos la ineficiencia porque implica sólo una pequeña fracción del costo total de computación. Mientras tanto, las operaciones intensivas se escriben en código altamente optimizado, a menudo código CUDA que se ejecuta en la GPU. Cada vez más, incluso estamos empezando a ver la inferencia LLM realizada en ASIC.
La criptografía programable moderna, como los SNARK, sigue nuevamente un patrón similar en dos niveles. En primer lugar, el probador se puede escribir en un lenguaje de alto nivel, donde el trabajo pesado se realiza mediante operaciones vectorizadas, como en el ejemplo de IA anterior. El código STARK circular que tengo aquí lo demuestra. En segundo lugar, los propios programas ejecutados dentro de la criptografía pueden escribirse de una manera que se divida entre la lógica empresarial general y el trabajo costoso y altamente estructurado.
Para entender cómo funciona esto, podemos observar una de las últimas tendencias demostradas por STARK. Para que sean versátiles y fáciles de usar, los equipos construyen cada vez más probadores STARK para máquinas virtuales mínimas ampliamente adoptadas, como RISC-V. Cualquier programa cuya ejecución deba probarse se puede compilar en RISC-V, y el probador puede luego probar la ejecución RISC-V de ese código.
Diagrama de la documentación de RiscZero
Esto es muy conveniente: significa que solo necesitamos escribir la lógica de prueba una vez y, a partir de ese momento, cualquier programa que necesite una prueba se puede escribir en cualquier lenguaje de programación "tradicional" (por ejemplo, RiskZero admite Rust). Sin embargo, hay un problema: este enfoque genera muchos gastos generales. El cifrado programable ya es prohibitivamente costoso; agregar la sobrecarga de ejecutar código en el intérprete RISC-V es demasiado. Entonces, a los desarrolladores se les ocurrió un truco: identificar las costosas operaciones específicas que constituyen la mayor parte del cálculo (generalmente hashes y firmas) y luego crear módulos especializados para probar esas operaciones de manera muy eficiente. Luego simplemente combina un sistema de prueba RISC-V ineficiente pero general con un sistema de prueba eficiente pero especializado y obtiene lo mejor de ambos mundos.
El cifrado programable distinto de ZK-SNARK, como la computación multipartita (MPC) y el cifrado totalmente homomórfico (FHE), se puede optimizar utilizando métodos similares.
En general, ¿cómo es el fenómeno?
La informática moderna sigue cada vez más lo que yo llamo arquitecturas de coprocesador y pegamento: tiene un componente "pegamento" central, que es muy versátil pero ineficiente, responsable de ejecutar tareas entre uno o más componentes del coprocesador. Estos componentes del coprocesador tienen baja generalidad pero alta eficiencia para transferir. datos entre ellos.
Se trata de una simplificación: en la práctica, la curva de equilibrio entre eficiencia y versatilidad casi siempre tiene más de dos niveles. Las GPU y otros chips, a menudo denominados en la industria "coprocesadores", son menos versátiles que las CPU pero más versátiles que los ASIC. La compensación de la especialización es compleja y depende de las predicciones y la intuición sobre qué partes del algoritmo seguirán siendo las mismas en cinco años y qué partes cambiarán en seis meses. En la arquitectura de prueba ZK, a menudo vemos múltiples capas de especialización similares. Pero para modelos mentales amplios, basta considerar dos niveles. Existen situaciones similares en muchas áreas de la informática:
De los ejemplos anteriores, ciertamente parece una ley natural que los cálculos se puedan dividir de esta manera. De hecho, se pueden encontrar ejemplos de especialización informática que abarcan décadas. Sin embargo, creo que esta separación está aumentando. Creo que hay una razón para esto:
Recientemente hemos alcanzado los límites de las mejoras en la velocidad del reloj de la CPU, por lo que sólo se pueden lograr mayores ganancias mediante la paralelización. Sin embargo, es difícil razonar sobre la paralelización, por lo que a menudo es más práctico para los desarrolladores continuar razonando secuencialmente y dejar que la paralelización ocurra en el backend, envuelta en módulos especializados creados para operaciones específicas.
Sólo recientemente las velocidades computacionales se han vuelto tan rápidas que el costo computacional de la lógica de negocios se ha vuelto realmente insignificante. En este mundo, también tiene sentido optimizar las máquinas virtuales en las que se ejecuta la lógica empresarial para lograr objetivos distintos de la eficiencia computacional: facilidad de uso para los desarrolladores, familiaridad, seguridad y otros objetivos similares. Mientras tanto, los módulos de "coprocesador" dedicados pueden seguir diseñándose para lograr eficiencia y obtener su seguridad y facilidad de uso para los desarrolladores de su "interfaz" relativamente simple con el adhesivo.
Cada vez está más claro cuáles son las operaciones costosas más importantes. Esto es más evidente en la criptografía, donde es más probable que se utilicen ciertos tipos de operaciones costosas: operaciones de módulo, combinaciones lineales de curvas elípticas (también conocidas como multiplicación multiescalar), transformadas rápidas de Fourier, etc. Esto también se está volviendo cada vez más evidente en la inteligencia artificial, donde durante más de dos décadas la mayoría de los cálculos han sido "principalmente multiplicaciones de matrices" (aunque con distintos niveles de precisión). Están surgiendo tendencias similares en otras áreas. Hay muchas menos incógnitas en la computación (intensiva) que hace 20 años.
¿qué significa eso?
Un punto clave es que los encoladores deben optimizarse para ser buenos encoladores y los coprocesadores deben optimizarse para ser buenos coprocesadores. Podemos explorar las implicaciones de esto en varias áreas clave.
EVM
Una máquina virtual blockchain (por ejemplo, EVM) no necesita ser eficiente, sólo familiar. Con solo agregar los coprocesadores adecuados (también conocido como "precompilación"), los cálculos en una VM ineficiente pueden ser tan eficientes como los cálculos en una VM nativamente eficiente. Por ejemplo, la sobrecarga incurrida por los registros de 256 bits de EVM es relativamente pequeña, mientras que los beneficios de la familiaridad de EVM y el ecosistema de desarrolladores existente son sustanciales y duraderos. Los equipos de desarrollo que optimizan EVM incluso han descubierto que la falta de paralelización a menudo no es una barrera importante para la escalabilidad.
La mejor manera de mejorar EVM podría ser simplemente (i) agregar mejores códigos de operación precompilados o especializados, por ejemplo, alguna combinación de EVM-MAX y SIMD podría ser razonable, y (ii) mejorar el diseño de la memoria, por ejemplo, de los árboles Verkle. , como efecto secundario, reduce en gran medida el costo de acceder a las ranuras de almacenamiento adyacentes entre sí.
Optimización del almacenamiento en la propuesta del árbol Ethereum Verkle, colocando claves de almacenamiento adyacentes juntas y ajustando el costo del gas para reflejar esto. Optimizaciones como esta, junto con una mejor precompilación, pueden ser más importantes que ajustar el propio EVM.
Computación segura y hardware abierto
Uno de los desafíos para mejorar la seguridad en la informática moderna a nivel de hardware es su naturaleza demasiado compleja y patentada: los chips están diseñados para ser eficientes, lo que requiere una optimización patentada. Las puertas traseras son fáciles de ocultar y constantemente se descubren vulnerabilidades de los canales laterales.
Continúan los esfuerzos para impulsar alternativas más abiertas y seguras desde múltiples ángulos. Parte de la informática se realiza cada vez más en entornos de ejecución confiables, incluidos los teléfonos de los usuarios, lo que ha mejorado la seguridad de los usuarios. El impulso por más hardware de consumo de código abierto continúa, con algunas victorias recientes, como las computadoras portátiles RISC-V con Ubuntu.
Computadora portátil RISC-V con Debian
Sin embargo, la eficiencia sigue siendo un problema. El autor del artículo vinculado anteriormente escribe:
Es poco probable que los diseños de chips de código abierto más nuevos, como RISC-V, compitan con la tecnología de procesador que ya existe y se ha perfeccionado durante décadas. El progreso siempre tiene un punto de partida.
Las ideas más paranoicas, como este diseño de construir una computadora RISC-V en una FPGA, enfrentan mayores gastos generales. Pero ¿qué pasa si el pegado y la arquitectura del coprocesador significan que esta sobrecarga en realidad no importa? Si aceptamos que los chips abiertos y seguros serán más lentos que los propietarios, incluso abandonando optimizaciones comunes como la ejecución especulativa y la predicción de ramas si es necesario, pero tratando de compensar esto agregando módulos ASIC (si es necesario, propietarios) que se utilizan en la mayoría de los intensivos. tipos específicos de cálculos, ¿qué pasa con eso? Se pueden realizar cálculos sensibles en un "chip maestro" que se optimizará en cuanto a seguridad, diseño de código abierto y resistencia de canal lateral. Se realizarán cálculos más intensivos (por ejemplo, pruebas ZK, AI) en módulos ASIC, que conocerán menos información sobre los cálculos que se realizan (posiblemente, mediante cegamiento criptográfico, incluso cero información en algunos casos).
criptografía
Otro punto clave es que todo esto es muy optimista acerca de la criptografía, especialmente la criptografía programable que se está volviendo común. Hemos visto algunas implementaciones hiperoptimizadas de ciertos cálculos altamente estructurados en SNARK, MPC y otras configuraciones: algunas funciones hash son solo unos cientos de veces más caras que ejecutar el cálculo directamente, y la inteligencia artificial (principalmente la multiplicación de matrices) también es muy bajo. Otras mejoras, como GKR, pueden reducir aún más este nivel. Una ejecución de VM completamente genérica, especialmente cuando se ejecuta en un intérprete RISC-V, probablemente seguiría generando aproximadamente diez mil veces más gastos generales, pero por las razones descritas en este artículo, esto no importa: siempre y cuando se utilicen técnicas especializadas eficientes. utilizados respectivamente Al manejar las partes con mayor uso computacional, el costo total es controlable.
Diagrama simplificado de MPC dedicado a la multiplicación de matrices, el componente más grande en la inferencia del modelo de IA. Consulte este artículo para obtener más detalles, incluido cómo mantener privados su modelo y sus entradas.
Una excepción a la idea de que "las capas de pegamento sólo necesitan ser familiares, no eficientes" es la latencia y, en menor medida, el ancho de banda de datos. Si el cálculo implica operaciones pesadas con los mismos datos docenas de veces (como en la criptografía y la inteligencia artificial), entonces cualquier retraso causado por capas de pegamento ineficientes puede convertirse en un cuello de botella importante en el tiempo de ejecución. Por tanto, las líneas de cola también tienen requisitos de eficiencia, aunque estos requisitos son más específicos.
en conclusión
En general, creo que las tendencias mencionadas son avances muy positivos desde múltiples perspectivas. En primer lugar, es una forma lógica de maximizar la eficiencia computacional sin dejar de ser amigable para los desarrolladores, y poder obtener más de ambas cosas es bueno para todos. En particular, mejora nuestra capacidad para ejecutar cálculos sensibles y que exigen rendimiento (por ejemplo, pruebas ZK, inferencia LLM) localmente en el hardware del usuario al permitir la especialización en el lado del cliente para una mayor eficiencia. En segundo lugar, crea una enorme ventana de oportunidades para garantizar que la búsqueda de eficiencia no comprometa otros valores, en particular la seguridad, la apertura y la simplicidad: seguridad de canal lateral y apertura en el hardware informático, reducción de la complejidad del circuito en ZK-SNARK y reducción Complejidad en máquinas virtuales. Históricamente, la búsqueda de la eficiencia ha hecho que estos otros factores pasen a un segundo plano. Con la arquitectura de pegamento y coprocesador, ya no es necesario. Una parte de la máquina optimiza la eficiencia, otra parte optimiza la versatilidad y otros valores, y las dos trabajan juntas.
Esta tendencia también es muy buena para la criptografía, que en sí misma es un excelente ejemplo de "computación estructurada costosa" y esta tendencia acelera esta tendencia. Esto añade otra oportunidad para mejorar la seguridad. También es posible mejorar la seguridad en el mundo blockchain: podemos preocuparnos menos por optimizar la máquina virtual y centrarnos más en optimizar la precompilación y otras características que coexisten con la máquina virtual.
En tercer lugar, esta tendencia brinda oportunidades para que participen actores más pequeños y nuevos. Si la informática se vuelve menos monolítica y más modular, esto reducirá significativamente la barrera de entrada. Incluso usar un ASIC para un tipo de computación puede marcar la diferencia. Esto también es válido en el ámbito de las pruebas ZK y la optimización EVM. Escribir código con una eficiencia casi de vanguardia se vuelve más fácil y accesible. Auditar y verificar formalmente dicho código se vuelve más fácil y accesible. Finalmente, debido a que estas áreas tan diferentes de la informática están convergiendo en algunos patrones comunes, hay más espacio para la colaboración y el aprendizaje entre ellas.