language golang benchmarksgame benchmark alioth c performance rust

golang - rust vs c



¿Por qué un programa que actualiza una gran matriz de coma flotante estática más lenta en Rust que en C? (1)

Rust compila el ciclo para:

.LBB0_1: movupd xmm0, xmmword ptr [rcx + 8*rax - 48] movupd xmm1, xmmword ptr [rcx + 8*rax - 32] addpd xmm0, xmm0 addpd xmm1, xmm1 movupd xmmword ptr [rcx + 8*rax - 48], xmm0 movupd xmmword ptr [rcx + 8*rax - 32], xmm1 movupd xmm0, xmmword ptr [rcx + 8*rax - 16] movupd xmm1, xmmword ptr [rcx + 8*rax] addpd xmm0, xmm0 addpd xmm1, xmm1 movupd xmmword ptr [rcx + 8*rax - 16], xmm0 movupd xmmword ptr [rcx + 8*rax], xmm1 add rax, 8 cmp rax, 100006 jne .LBB0_1

Mientras que GCC 7.1.0 compila a:

L6: movsd (%rbx), %xmm0 addq $8, %rbx addsd %xmm0, %xmm0 movsd %xmm0, -8(%rbx) cmpq %rbp, %rbx jne L6

Rust coloca la matriz en una sección de datos, mientras que C escribe ( memset con patrón) en la memoria. Esto significa que su sistema operativo que ejecuta la aplicación probablemente solo asigna el rango y depende de la memoria virtual para hacer lo correcto.

Si cambia el código para ejecutar el mismo ciclo antes de la medición, el tiempo de ejecución baja considerablemente. En realidad es más rápido que la versión C en mi máquina. (posiblemente debido a ese bucle que se desenrolla)

unsafe { for i in 0..STREAM_ARRAY_SIZE { A[i] = 2.0E0 * A[i]; } } let now = Instant::now(); unsafe { for i in 0..STREAM_ARRAY_SIZE { A[i] = 2.0E0 * A[i]; } } let duration = now.elapsed();

Escribí un programa simple para comparar el rendimiento de Rust y C

La versión de Rust:

use std::time::Instant; const STREAM_ARRAY_SIZE: usize = 10000000; static mut A: [f64; STREAM_ARRAY_SIZE] = [1.0; STREAM_ARRAY_SIZE]; fn main() { let now = Instant::now(); unsafe { for i in 0..STREAM_ARRAY_SIZE { A[i] = 2.0E0 * A[i]; } } let duration = now.elapsed(); println!("{}", (duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64) / 1000); }

Ejecútelo en modo de depuración y liberación:

$ ./target/debug/calc 472046 us. $ ./target/release/calc 62860 us.

La versión de lanzamiento tiene una ganancia de rendimiento drástica en comparación con la depuración.

La versión C hace lo mismo y se ejecuta en el mismo servidor:

#include <sys/time.h> #include <stdio.h> #define STREAM_ARRAY_SIZE 10000000 static double A[STREAM_ARRAY_SIZE]; int mysecond(void) { struct timeval tp; struct timezone tzp; int i; i = gettimeofday(&tp,&tzp); return (tp.tv_sec * 1000000 + tp.tv_usec); } int main(void) { int j = 0; for (j = 0; j < STREAM_ARRAY_SIZE; j++) { A[j] = 1.0; } int t = mysecond(); for (j = 0; j < STREAM_ARRAY_SIZE; j++) { A[j] = 2.0E0 * A[j]; } printf("%d us./n", mysecond() - t); return 0; }

Compilar y ejecutarlo con -O0 y -O2 :

$ gcc test.c $ ./a.out 41626 us. $ gcc -O2 test.c $ ./a.out 13499 us.

La versión optimizada de Rust solo se compara con gcc -O0 , y es muy débil en comparación con gcc -O2 . Es esto razonable? ¿Cómo puedo mejorar el rendimiento de la versión Rust?