Byte Sieve es una implementación informática de la Criba de Eratóstenes publicada por Byte como referencia de rendimiento de lenguajes de programación . Apareció por primera vez en la edición de septiembre de 1981 de la revista y fue revisada en ocasiones. Aunque su objetivo era comparar el rendimiento de diferentes lenguajes en las mismas computadoras, rápidamente se convirtió en una referencia de máquina ampliamente utilizada.
El Sieve fue uno de los benchmarks más populares de la era de los ordenadores domésticos , junto con el Creative Computing Benchmark de 1983 y los benchmarks Rugg/Feldman , que se utilizaban principalmente en el Reino Unido en esa época. Byte publicó más tarde el NBench, más completo, en 1995 para sustituirlo.
Jim Gilbreath, del Naval Ocean System Center, había estado considerando el concepto de escribir un pequeño programa de evaluación comparativa de lenguajes durante algún tiempo, deseando uno que fuera portable entre lenguajes, lo suficientemente pequeño como para que el código del programa cupiera en una sola página impresa y que no dependiera de características específicas como la multiplicación o división de hardware. La solución se inspiró en una reunión con Chuck Forsberg en la reunión de USENIX de enero de 1980 en Boulder, Colorado , donde Forsberg mencionó una implementación del tamiz escrito por Donald Knuth . [1] [2]
Gilbreath consideró que el tamiz sería un punto de referencia ideal, ya que evitaba las pruebas indirectas sobre el rendimiento aritmético, que variaba ampliamente entre sistemas. El algoritmo enfatiza principalmente el rendimiento de búsqueda en matrices y las capacidades de lógica y ramificación básicas. Tampoco requiere ninguna característica avanzada del lenguaje como la recursión o los tipos de colección avanzados. La única modificación de la versión original de Knuth fue eliminar una multiplicación por dos y reemplazarla con una suma. Con la versión original, las máquinas con multiplicadores de hardware funcionarían mucho más rápido que el resto del rendimiento quedaría oculto. [1]
Después de seis meses de esfuerzo para adaptarlo a tantas plataformas como tuviera acceso, los primeros resultados se presentaron en la edición de septiembre de 1981 de Byte en un artículo titulado "A High-Level Language Benchmark" [1] . Gilbreath se apresuró a señalar que:
Debo enfatizar que este parámetro no es el único criterio para juzgar un lenguaje o compilador. [1]
El artículo proporcionó implementaciones de referencia en diez lenguajes, incluidas selecciones más populares como BASIC , C , Pascal , COBOL y FORTRAN , y algunos ejemplos menos conocidos como Forth , ZSPL , Ratfor , PL/1 y PLMX . [3]
Se proporcionaron ejemplos de ejecución para una variedad de máquinas, principalmente basadas en Zilog Z80 o MOS 6502. El mejor tiempo fue inicialmente de 16,5 segundos, obtenido por Ratfor en una máquina Z80 de 4 MHz, pero Gary Kildall proporcionó personalmente una versión en la versión prototipo de PL/1 de Digital Research [4] que se ejecutó en 14 segundos y estableció la marca para esta primera colección. El más lento fue Microsoft COBOL en la misma máquina, que tardó la friolera de 5115 segundos (casi una hora y media), más tiempo incluso que los lenguajes interpretados como BASIC. [5] Una característica notable de esta primera ejecución fue que C, Pascal y PL/1 obtuvieron un rendimiento aproximadamente similar que superó fácilmente a los diversos intérpretes. [4]
Se llevó a cabo un segundo conjunto de pruebas en máquinas más potentes, y el lenguaje ensamblador Motorola 68000 fue el más rápido, con 1,12 segundos, superando ligeramente al C en un PDP-11/70 y casi el doble de rápido que el ensamblador 8086. La mayoría de los tiempos de las PDP-11 y HP-3000 fueron mucho más lentos, del orden de 10 a 50 segundos. [6] Las pruebas en estas máquinas utilizando solo lenguajes de alto nivel fueron lideradas por NBS Pascal en la PDP-11, con 2,6 segundos. [7]
UCSD Pascal proporcionó otro conjunto interesante de resultados, ya que el mismo programa se puede ejecutar en varias máquinas. Al ejecutarse en la máquina dedicada Ithaca InterSystems Pascal-100, una computadora basada en Pascal MicroEngine , se ejecutó en 54 segundos, mientras que en el Z80 fue de 239 y de 516 en el Apple II. [7]
Gilbreath, esta vez junto con su hermano Gary, revisó el código en la edición de enero de 1983 de Byte . Esta versión eliminó la mayoría de los lenguajes menos populares, dejando Pascal, C, FORTRAN IV y COBOL, mientras que agregó Ada y Modula-2 . Gracias a los lectores que proporcionaron muestras adicionales, la cantidad de máquinas, sistemas operativos e idiomas comparados en las tablas resultantes se amplió en gran medida. [8]
El ensamblaje Motorola 68000 (68k) siguió siendo el más rápido, casi tres veces la velocidad del Intel 8086 funcionando al mismo reloj de 8 MHz. Usando lenguajes de alto nivel, los dos estaban más cerca en rendimiento, con el 8086 generalmente mejor que la mitad de la velocidad del 68k y a menudo mucho más cerca. [9] También se incluyó una variedad más amplia de minicomputadoras y mainframes , con tiempos que el 68k generalmente superó, excepto por las máquinas más rápidas como el IBM 3033 y los modelos de alta gama del VAX . Máquinas más antiguas como el Data General Nova , PDP-11 y HP-1000 no eran tan rápidas como el 68k. [8]
El segundo artículo de Gilbreath apareció cuando el benchmark se estaba volviendo bastante común como una forma de comparar el rendimiento de varias máquinas, y más aún de lenguajes. A pesar de su advertencia original de no hacerlo, pronto comenzó a aparecer en anuncios de revistas como una forma de comparar el rendimiento con la competencia, [10] [11] y como un benchmark general. [12]
Byte volvió a utilizar el tamiz más tarde, en agosto de 1983, como parte de una serie de artículos de toda una revista sobre el lenguaje C. En este caso, el uso se ajustaba más a la intención original, utilizando un único código fuente y ejecutándolo en una única máquina para comparar el rendimiento de los compiladores de C en el sistema operativo CP/M-86 , [13] en CP/M-80 , [14] y para el IBM PC . [15]
A pesar de la preocupación de Gilbreath en el artículo original, en ese momento el código se había vuelto casi universal para pruebas, y uno de los artículos remarcó que "La criba de Eratóstenes es un punto de referencia obligatorio". [13] Fue incluido en el Byte UNIX Benchmark Suite presentado en agosto de 1984. [16]
Siguen apareciendo nuevas versiones del código para nuevos lenguajes, [17] por ejemplo, Rosetta Code y GitHub tienen muchas versiones disponibles. [18] A menudo se utiliza como un ejemplo de programación funcional a pesar de que la versión común en realidad no utiliza el algoritmo de tamiz. [19]
La implementación proporcionada solo calculaba primos impares, por lo que la matriz de 8191 elementos en realidad representaba primos menores que 16385. Como se muestra en una tabla de la barra lateral, el elemento 0 representaba 3, el primer elemento 5, el segundo elemento 7, y así sucesivamente.
Esta es la versión BASIC original del código presentado en 1981. [20] [a] No se especifica el dialecto, pero una serie de detalles indican que no funciona en las primeras versiones de Microsoft BASIC (4.x y anteriores), entre ellos el uso de nombres de variable largos como SIZE
y FLAGS
. La falta de números de línea puede sugerir una variedad de minicomputadora que lee el código fuente desde un archivo de texto, pero también puede haber sido un error de impresión.
Programa de números primos de la criba de Eratóstenes de REM en BASIC 1 TAMAÑO = 8190 2 DIM FLAGS ( 8191 ) 3 PRINT "Solo 1 iteración" 5 COUNT = 0 6 FOR I = 0 TO SIZE 7 FLAGS ( I ) = 1 8 NEXT I 9 FOR I = 0 TO SIZE 10 IF FLAGS ( I ) = 0 THEN 18 11 PRIME = I + I + 3 12 K = I + PRIME 13 IF K > SIZE THEN 17 14 FLAGS ( K ) = 0 15 K = K + PRIME 16 GOTO 13 17 COUNT = COUNT + 1 18 NEXT I 19 PRINT COUNT , " PRIMES"
Y en C, con algunos ajustes de espacios en blanco respecto del original: [21]
#define verdadero 1 #define falso 0 #define tamaño 8190 #define tamañopl 8191 char flags [ sizepl ]; main () { int i , primo , k , conteo , iter ; printf ( "10 iteraciones \n " ); for ( iter = 1 ; iter <= 10 ; iter ++ ) { conteo = 0 ; for ( i = 0 ; i <= tamaño ; i ++ ) flags [ i ] = verdadero ; for ( i = 0 ; i <= tamaño ; i ++ ) { if ( flags [ i ]) { primo = i + i + 3 ; k = i + primo ; while ( k <= tamaño ) { flags [ k ] = falso ; k += primo ; } conteo = conteo + 1 ; } } } printf ( " \n %d primos" , conteo ); }