Autor Tema: i.MX RT de NXP, Cortex M7 500-600 Mhz  (Leído 289 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Conectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2866
i.MX RT de NXP, Cortex M7 500-600 Mhz
« en: 23 de Enero de 2018, 22:51:28 »
.

Otro bicho imponente, la gama i.MX RT de NXP, Cortex M7, el RT1050 a 600Mhz, y el RT1020 a 500Mhz (saldrá en Marzo).

Lo bueno es que están soportados por MCUExpresso, con sus fantásticos asistentes integrados, Config Tools, Clock, Periféricos, todo en un entorno de configuración gráfica como el CubeMx de ST.

No me he podido resistir, y me he pedido la placa de evaluación del RT1050, son 74 euros en Mouser, y opcional la pantalla por otros 37.

Mi idea es usar el RT1020 para mis diseños, porque será TQFP, mientras que el RT1050 solo está en BGA. Para ir probando el desarrollo en MCUExpreso me sirve igual.

NXP va haciendo camino, solo le falta cambiar su política de distribución, que ahora es un desastre, para que el producto se consiga con facilidad.

https://www.nxp.com/products/processors-and-microcontrollers/applications-processors/i.mx-applications-processors/i.mx-rt-series:IMX-RT-SERIES





Desconectado george.manson.69

  • PIC10
  • *
  • Mensajes: 27
    • Microcontroladores en General
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #1 en: 25 de Enero de 2018, 20:42:27 »
¡Hermosa Tarjeta!  :)

¡Saludos!

Conectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2866
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #2 en: 14 de Febrero de 2018, 11:00:39 »
 

A poco de que NXP libere su nuevo microcontrolador i.MX RT1020 Cortex M7 a 500Mhz, se espera para principios de Marzo. A ver si me hago con unos samples y monto una plaquita de evaluación, estos son en TQFP100 y TQFP144, a diferencia del RT1050 en BGA.

De momento no hay Datasheet disponible, pero ya hay información sobre las prestaciones del micro. El precio desde una unidad no lo han fijado todavía, pero para las preorders de 90 unidades en Digikey y Avnet están a 4.2 Dólares, supongo que para unidades sueltas rondará los 7-8 dólares en Europa y más baratos en China, que para las prestaciones que tiene, es una pasada.

La particularidad de estos microcontroladores, es que no tienen memoria flash, hay que añadir el sistema de arranque desde fuera, con memorias paralelo hyperflash, serie QSPI o tarjetero SD. Mi idea es crear mi placa de evaluación, y diseños posteriores para arranque desde SD, así prácticamente no hay limitación para el tamaño del programa.

Crear una plaquita pequeña, algo similar al Teensy, puede quedar muy bien, de hecho en los foros oficiales de Teensy, el creador indicó hace tiempo que probablemente el nuevo Teensy 4.0 instalará este microcontrolador, lo cual sería una noticia genial, porque tendríamos librerías a cascoporro, gratis para hacer de todo, la nota mala es si sigue usando el IDE de Arduino, en vez de migrar a MCUExpresso.
















« Última modificación: 14 de Febrero de 2018, 11:35:35 por planeta9999 »

Desconectado tsk

  • PIC16
  • ***
  • Mensajes: 179
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #3 en: 14 de Febrero de 2018, 15:49:03 »
Se ven interesantes esos microcontroladores, si es que todavía se les puede llamar así, jejejeje.

Aunque el problema que les veo, dada la ignoracia de que todavía no he probado un ARM Cortex M7 es el hecho de que tengan un pipeline de 6 etapas.

Si el algoritmo que manejamos tiene alta dependencia en datos, la potencia ganada con los 500 o 600Mhz se podría ver diluida.

Ya lo había mostrado en el del CRC por hardware vs por software, donde un aproximado de 13 ciclos por iteración se convierte en 21 ciclos dada esa dependencia de datos y un pipeline de 2 en un ARM Cortex M3 (stm32f103c8t6).

Aunque se que se tendría que ver y aprovechar la memoria caché (¿Será como la TCM/CCM algunos M4?) con la que cuenta, pero por el momento sólo se me ocurre echar números y pensar que un incremento de 72Mhz a 500Mhz (6.94x) me representaría el mismo incremento del performance por la misma cantidad, pero en la realidad sólo me representaría un incremento de 3.93x, que en definitiva es bueno, pero ¿que tan bueno podría ser? considerando factores como el consumo de potencia.

Creo que le voy a comenzar a echar mano a los ARM Cortex M7 para quitarme las dudas.

Saludos.

Conectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2866
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #4 en: 14 de Febrero de 2018, 17:08:52 »

Aunque el problema que les veo, dada la ignoracia de que todavía no he probado un ARM Cortex M7 es el hecho de que tengan un pipeline de 6 etapas.


¿ Donde has leido lo de las 6 etapas ?, yo he leído que son 3 etapas en los Cortex M7, y que en todo caso mejoran el rendimiento.

A mi lo que me preocupa es que el software queda fuera del micro, por lo tanto cualquiera puede leer el objeto (y desensamblarlo). Solo se me ocurre poner un sistema de licencia usando el ID único que supongo tendrá cada chip.

También me preocupaba que este soportado por MCUExpresso, para poder usar las Config Tools y todos los asistentes para configurar la periferia sin necesidad de escribir código, igual que lo hace Cubemx con los ST.

El precio parece que va a ser muy bueno, para las prestaciones que tiene, solo falta por ver si NXP cambia su política de distribución y no deja tirada a la gente con plazos de entrega de 39 semanas como ha pasado con los Kinetis.

Yo ya lo tengo todo listo para diseñar una plaquita de evaluación, en cuanto consiga unos samples. Pondré las mismas memorias hyperflash, QSPI y tarjetero SDIO que instala la placa de evaluación del RT1050, para el sistema de arranque y almacenaje del firmware. Quiero probar las tres opciones, a ver cual es la mejor, o si conviene una mezcla de varias, incluso una RAM externa para que cargue desde SD y ejecute en RAM.

Creo que la RAM también se puede ampliar externamente, aparte de los 256K que tiene el chip.






« Última modificación: 14 de Febrero de 2018, 17:22:51 por planeta9999 »

Desconectado tsk

  • PIC16
  • ***
  • Mensajes: 179
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #5 en: 14 de Febrero de 2018, 17:34:18 »
De aquí lo he leído:

https://developer.arm.com/products/processors/cortex-m/cortex-m7

Citar
6-stage superscalar + branch prediction

Conectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2866
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #6 en: 14 de Febrero de 2018, 19:15:22 »
De aquí lo he leído:

https://developer.arm.com/products/processors/cortex-m/cortex-m7

Citar
6-stage superscalar + branch prediction


¿ Y eso puede perjudicar el rendimiento ?, por lo que he leído, ese pipeline de 6 etapas supone que podrá ejecutar 2 intrucciones en paralelo.




Desconectado tsk

  • PIC16
  • ***
  • Mensajes: 179
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #7 en: 14 de Febrero de 2018, 19:26:51 »
Es un procesador superscalar, por lo tanto, tentativamente podría estar ejecutando dos o más instrucciones al mismo tiempo, dependiendo de la arquitectura del procesador.

Pero depende bastante de nuestro algoritmo.

Si es algo de estilo

a = b + c;
d = e + f;

Las dos instrucciones van a entrar al mismo tiempo, pero si hay dependencia de datos es donde se va a mostrar la reducción del rendimiento, ya que va a tener que detener la ejecución de la instrucción para esperar a que los datos estén disponibles y ese tiempo son por lo menos 6 ciclos de reloj más los ciclos propios de la instrucción a ejecutar.

------------

De aquí
https://en.wikipedia.org/wiki/Superscalar_processor
Muestran que los retardos pueden ser del orden de k^2*log(n) donde n es el numero de instrucciones en el ISA del procesador y k la cantidad de instrucciones que se pueden despachar de forma simultánea.
« Última modificación: 14 de Febrero de 2018, 19:39:37 por tsk »

Conectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2866
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #8 en: 14 de Febrero de 2018, 19:47:59 »


Ok, entiendo.
Supongo que eso también afecta igual a los procesadores de varios nucleos y a los clusters.

Desconectado tsk

  • PIC16
  • ***
  • Mensajes: 179
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #9 en: 14 de Febrero de 2018, 20:46:09 »
Si y de hecho ciertas cosas tienden a ser un poco más complicadas.

Continuando con la dependencia de datos en los procesadores modernos lo podemos resumir como tres niveles de memoria, de acuerdo a que tan cercanos se encuentran al procesador:

- Registros
- Caché
- RAM

Los registros, que es donde se realizan las operaciones es la memoria que está mas cercana al procesador y es la más rápida de todas, pero también es la más costosa, así que te ayudas de la Caché y la RAM para almacenar los datos sobre los que estás operando.

En los microprocesadores modernos a la hora que solicitas el contenido de una variable primero la busca en la caché, si está, se le conoce como un hit, si no está entonces es un miss y va a la RAM para traer esa variable a la caché junto con otras regiones de memoria que se encuentran cercanas porque existe cierta probabilidad de que vayan a ser usadas. Así cuando busque de nuevo una variable en la caché, se va a incrementar la probabilidad de un hit.

Supongamos que tenemos una matriz sobre la cual vas a iterar, en el momento que hagas un a = M[0][0] al no encontrarse en la caché la va a traer de la RAM a la caché junto con M[0][1],M[0][2],... , de tal forma que en la siguiente iteración que sea a = M[0][1] ya la va a tener disponible en la memoria caché. Pero si somos tan cabezones que hacemos un a = M[0][0], pero luego hacemos un b = M[1][0] y si hacemos la suposición que en la caché solo entra una fila, entonces vamos a estar reescribiendo el contenido de la caché en cada iteración en dos ocasiones ya que todos los accesos a memoria van a ser un miss en lugar de un hit.

Por ese motivo entre más caché tenga el procesador es mejor, pero también es más costoso.

Aunque este modelo también presenta sus problemas se ha demostrado que incrementa, por lo general y en la mayoría de los casos, el rendimiento del sistema.

Así que si estamos al tanto de como trabaja el procesador y la forma en que el lenguaje de programación almacena los datos vamos a poder desarrollar algoritmos que estén mejor adaptados y optimizados para dicha arquitectura, en caso de que sea necesario realizar optimizaciones cuando tengamos cuellos de botella.

Por ejemplo, no es lo mismo iterar en una matriz por filas o por columnas ( (i,k) o (k,i) ) dependiendo del lenguaje de programación

En C es mejor hacerlo por (i,k), en cambio en Fortran es mejor (k,i) ya que a diferencia de C  en Fortran las matrices las almacena por columnas no por filas.

Conectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2866
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #10 en: 15 de Febrero de 2018, 07:56:13 »

Gracias, muy interesante.
A veremos en la práctica si nos afecta el rendimiento tanto. No se si todo eso se puede paliar con la programación, o es lo que hay hagas lo que hagas.

Esto espectante y muy interesado con este micro, me parece que el salto es espectacular, y además el precio parece que va a ser de baratija comparado con los Kinetis y con otros ARM del mercado, porque los SMT32H7 son carísimos y mucho más flojos en prestaciones. Si además los chinos lo pueden ofrecer a buen precio, confio en conseguirlo a 5 ó 6 dólares, puede incluso que a ese precio en Mouser.

Si no fuera por las prestaciones actuales de MCUEXpresso con las Config Tools, y porque muy probablemente será el chip que monte el nuevo Teensy 4.0, sería un micro más con prestaciones increibles, pero sin ningún tipo de  ayuda para el desarrollo. Esto es en lo que deberían caer muchos fabricantes, en ofrecer un buen soporte en librerías y código de ejemplo, así se crea mercado.

Desconectado tsk

  • PIC16
  • ***
  • Mensajes: 179
Re:i.MX RT de NXP, Cortex M7 500-600 Mhz
« Respuesta #11 en: 15 de Febrero de 2018, 15:01:32 »
Es lo que hay pero por eso cuando se requiere incrementar el rendimiento se trabaja con algoritmos, estructuras de datos, el orden en que ponemos las instrucciones y el conocimiento de las herramientas que vamos a usar (por ejemplo el compilador, el lenguaje, el interprete, etc).

Hay aprovechar todo lo que nos permitan usar de una mejor forma lo que nos ofrece el sistema y eso es por lo general por software. Sin ir más lejos

No es lo mismo

Código: C
  1. for()
  2. {
  3. }
  4.  
a un

Código: C
  1. for()
  2. {
  3.   for()
  4.   {
  5.   }
  6. }
  7.  

y mucho menos a un

Código: C
  1. for()
  2. {
  3.   for()
  4.   {
  5.     for()
  6.     {
  7.     }
  8.   }
  9. }
  10.  

Imagina 3 for anidados en un procesador con pipeline.

No es lo mismo

Código: C
  1. struct {
  2. char c;
  3. int  i;
  4. }
  5.  
a

Código: C
  1. struct {
  2. char c;
  3. char pad[x]
  4. int i;
  5. }

donde x es un valor que nos permite forzar que la estructura ocupe una línea entera de la caché, sobre todo cuando la estructura es compartida entre varios procesos.

Hay técnicas que se conocen como loop unrolling, por lo general cuando el compilador detecta que puede, por así decirlo desenrollar un loop, lo va a hacer para optimizar la ejecución, de acuerdo a la plataforma.

Código: C
  1. #include <stdio.h>
  2.  
  3. int main(int argc, char **argv)
  4. {
  5.   int k = 0;
  6.   for( k = 0; k < 5; ++k )
  7.   {
  8.     volatile int temp = k;
  9.   }
  10. }
  11.  
  12.  

Código: ASM
  1. 0000000000400400 <main>:
  2.   400400:       c7 44 24 fc 00 00 00    movl   $0x0,-0x4(%rsp)
  3.   400407:       00
  4.   400408:       c7 44 24 fc 01 00 00    movl   $0x1,-0x4(%rsp)
  5.   40040f:       00
  6.   400410:       c7 44 24 fc 02 00 00    movl   $0x2,-0x4(%rsp)
  7.   400417:       00
  8.   400418:       c7 44 24 fc 03 00 00    movl   $0x3,-0x4(%rsp)
  9.   40041f:       00
  10.   400420:       c7 44 24 fc 04 00 00    movl   $0x4,-0x4(%rsp)
  11.   400427:       00
  12.   400428:       c3                      retq  
  13.  

En este caso, en el ARM Cortex M7, no tendría problemas en introducir dos instrucciones a la vez en el pipeline.

Si le aumentamos a iterar sobre 20 elementos

Código: ASM
  1. 0000000000400400 <main>:
  2.   400400:       31 c0                   xor    %eax,%eax
  3.   400402:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  4.   400408:       89 44 24 fc             mov    %eax,-0x4(%rsp)
  5.   40040c:       83 c0 01                add    $0x1,%eax
  6.   40040f:       83 f8 14                cmp    $0x14,%eax
  7.   400412:       75 f4                   jne    400408 <main+0x8>
  8.   400414:       f3 c3                   repz retq
  9.  

Pero le podemos ayudar un poco desenrollando el ciclo nosotros mismos.

Código: C
  1. #include <stdio.h>
  2.  
  3. volatile char temp0[20];
  4. volatile int  temp1[20];
  5.  
  6. int main(int argc, char **argv)
  7. {
  8.   int k,i = 0;
  9.   for( k = 0; k < 10; ++k )
  10.   {
  11.     temp0[i] = k;
  12.     temp0[i+1] = k +1;
  13.     temp1[i] = k;
  14.     temp1[i+1] = k +1;
  15.     i = i +2;
  16.   }
  17. }
  18.  
  19.  

Código: ASM
  1. 0000000000400400 <main>:
  2.   400400:       c6 05 59 0c 20 00 00    movb   $0x0,0x200c59(%rip)        # 601060 <temp0>
  3.   400407:       c6 05 53 0c 20 00 01    movb   $0x1,0x200c53(%rip)        # 601061 <temp0+0x1>
  4.   40040e:       c7 05 68 0c 20 00 00    movl   $0x0,0x200c68(%rip)        # 601080 <temp1>
  5.   400415:       00 00 00
  6.   400418:       c7 05 62 0c 20 00 01    movl   $0x1,0x200c62(%rip)        # 601084 <temp1+0x4>
  7.   40041f:       00 00 00
  8.   400422:       c6 05 39 0c 20 00 01    movb   $0x1,0x200c39(%rip)        # 601062 <temp0+0x2>
  9.   400429:       c6 05 33 0c 20 00 02    movb   $0x2,0x200c33(%rip)        # 601063 <temp0+0x3>
  10.   400430:       c7 05 4e 0c 20 00 01    movl   $0x1,0x200c4e(%rip)        # 601088 <temp1+0x8>
  11.   400437:       00 00 00
  12.   40043a:       c7 05 48 0c 20 00 02    movl   $0x2,0x200c48(%rip)        # 60108c <temp1+0xc>
  13.   400441:       00 00 00
  14.   400444:       c6 05 19 0c 20 00 02    movb   $0x2,0x200c19(%rip)        # 601064 <temp0+0x4>
  15.   40044b:       c6 05 13 0c 20 00 03    movb   $0x3,0x200c13(%rip)        # 601065 <temp0+0x5>
  16.   400452:       c7 05 34 0c 20 00 02    movl   $0x2,0x200c34(%rip)        # 601090 <temp1+0x10>
  17.   400459:       00 00 00
  18.   40045c:       c7 05 2e 0c 20 00 03    movl   $0x3,0x200c2e(%rip)        # 601094 <temp1+0x14>
  19.   400463:       00 00 00
  20.   400466:       c6 05 f9 0b 20 00 03    movb   $0x3,0x200bf9(%rip)        # 601066 <temp0+0x6>
  21.   40046d:       c6 05 f3 0b 20 00 04    movb   $0x4,0x200bf3(%rip)        # 601067 <temp0+0x7>
  22.   400474:       c7 05 1a 0c 20 00 03    movl   $0x3,0x200c1a(%rip)        # 601098 <temp1+0x18>
  23.   40047b:       00 00 00
  24.   40047e:       c7 05 14 0c 20 00 04    movl   $0x4,0x200c14(%rip)        # 60109c <temp1+0x1c>
  25.   400485:       00 00 00
  26.   400488:       c6 05 d9 0b 20 00 04    movb   $0x4,0x200bd9(%rip)        # 601068 <temp0+0x8>
  27.   40048f:       c6 05 d3 0b 20 00 05    movb   $0x5,0x200bd3(%rip)        # 601069 <temp0+0x9>
  28.   400496:       c7 05 00 0c 20 00 04    movl   $0x4,0x200c00(%rip)        # 6010a0 <temp1+0x20>
  29.   40049d:       00 00 00
  30.   4004a0:       c7 05 fa 0b 20 00 05    movl   $0x5,0x200bfa(%rip)        # 6010a4 <temp1+0x24>
  31.   4004a7:       00 00 00
  32.   4004aa:       c6 05 b9 0b 20 00 05    movb   $0x5,0x200bb9(%rip)        # 60106a <temp0+0xa>
  33.   4004b1:       c6 05 b3 0b 20 00 06    movb   $0x6,0x200bb3(%rip)        # 60106b <temp0+0xb>
  34.   4004b8:       c7 05 e6 0b 20 00 05    movl   $0x5,0x200be6(%rip)        # 6010a8 <temp1+0x28>
  35.   4004bf:       00 00 00
  36.   4004c2:       c7 05 e0 0b 20 00 06    movl   $0x6,0x200be0(%rip)        # 6010ac <temp1+0x2c>
  37.   4004c9:       00 00 00
  38.   4004cc:       c6 05 99 0b 20 00 06    movb   $0x6,0x200b99(%rip)        # 60106c <temp0+0xc>
  39.   4004d3:       c6 05 93 0b 20 00 07    movb   $0x7,0x200b93(%rip)        # 60106d <temp0+0xd>
  40.   4004da:       c7 05 cc 0b 20 00 06    movl   $0x6,0x200bcc(%rip)        # 6010b0 <temp1+0x30>
  41.   4004e1:       00 00 00
  42.   4004e4:       c7 05 c6 0b 20 00 07    movl   $0x7,0x200bc6(%rip)        # 6010b4 <temp1+0x34>
  43.   4004eb:       00 00 00
  44.   4004ee:       c6 05 79 0b 20 00 07    movb   $0x7,0x200b79(%rip)        # 60106e <temp0+0xe>
  45.   4004f5:       c6 05 73 0b 20 00 08    movb   $0x8,0x200b73(%rip)        # 60106f <temp0+0xf>
  46.   4004fc:       c7 05 b2 0b 20 00 07    movl   $0x7,0x200bb2(%rip)        # 6010b8 <temp1+0x38>
  47.   400503:       00 00 00
  48.   400506:       c7 05 ac 0b 20 00 08    movl   $0x8,0x200bac(%rip)        # 6010bc <temp1+0x3c>
  49.   40050d:       00 00 00
  50.   400510:       c6 05 59 0b 20 00 08    movb   $0x8,0x200b59(%rip)        # 601070 <temp0+0x10>
  51.   400517:       c6 05 53 0b 20 00 09    movb   $0x9,0x200b53(%rip)        # 601071 <temp0+0x11>
  52.   40051e:       c7 05 98 0b 20 00 08    movl   $0x8,0x200b98(%rip)        # 6010c0 <temp1+0x40>
  53.   400525:       00 00 00
  54.   400528:       c7 05 92 0b 20 00 09    movl   $0x9,0x200b92(%rip)        # 6010c4 <temp1+0x44>
  55.   40052f:       00 00 00
  56.   400532:       c6 05 39 0b 20 00 09    movb   $0x9,0x200b39(%rip)        # 601072 <temp0+0x12>
  57.   400539:       c6 05 33 0b 20 00 0a    movb   $0xa,0x200b33(%rip)        # 601073 <temp0+0x13>
  58.   400540:       c7 05 7e 0b 20 00 09    movl   $0x9,0x200b7e(%rip)        # 6010c8 <temp1+0x48>
  59.   400547:       00 00 00
  60.   40054a:       c7 05 78 0b 20 00 0a    movl   $0xa,0x200b78(%rip)        # 6010cc <temp1+0x4c>
  61.   400551:       00 00 00
  62.   400554:       c3                      retq  
  63.  

Ahí es donde entra nuestra capacidad de entender nuestro algoritmo y la arquitectura en la que estamos trabajando para incrementar el rendimiento en caso de necesitarlo. Si no hay necesidad, pues el rendimiento que obtenemos al incrementar la frecuencia de reloj podría ser más que suficiente.

En linux tenemos varias herramientas para perfilar el comportamiento de los programas, además que hay ciertos registros en la CPU que mantienen la información sobre eventos como cache load, cache miss, branch miss, entre otros.

Algunas de estas herramientas son

- perf que pertenece al kernel de linux
- oprofile
- papi
- cachegrind

Por ejemplo con perf vamos perfilar el comando sleep

Código: [Seleccionar]
sudo perf stat -a -B -e cache-references,cache-misses,cycles,instructions,branches,branch-misses,stalled-cycles-frontend,stalled-cycles-backend,faults,migrations,L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses sleep 5
Código: [Seleccionar]

 Performance counter stats for 'system wide':

     1 867 573 612 cache-references                                             [33.35%]
         3 945 227 cache-misses              #    0.211 % of all cache refs     [33.43%]
     5 881 494 734 cycles                    [33.46%]
     7 516 215 308 instructions              #    1.28  insns per cycle       
                                             #    0.02  stalled cycles per insn [33.46%]
     1 870 488 999 branches                                                     [33.38%]
         2 211 585 branch-misses             #    0.12% of all branches         [33.30%]
       154 909 407 stalled-cycles-frontend   #    2.63% frontend cycles idle    [33.27%]
       106 690 388 stalled-cycles-backend    #    1.81% backend  cycles idle    [33.27%]
               453 faults                                                       [100.00%]
                 0 migrations                                                 
     1 850 876 631 L1-dcache-loads                                              [33.27%]
         1 849 926 L1-dcache-load-misses     #    0.10% of all L1-dcache hits   [33.27%]
         7 101 574 LLC-loads                                                    [33.27%]
         2 079 920 LLC-load-misses           #   29.29% of all LL-cache hits    [33.27%]

       5.001107881 seconds time elapsed

Ahora voy a obtener los valores del siguiente script en python

Código: Python
  1. from xml.dom.minidom import parse, parseString
  2. from lxml import etree as ET
  3.  
  4. dom = parse("cadena.xml")
  5.  
  6. print("-------------------------")
  7.  
  8. for node in dom.getElementsByTagName("cfdi:Impuestos"):
  9.     print(node.getAttribute("TotalImpuestosTrasladados"))
  10.  
  11. #Con lxml.etree
  12.  
  13. d = ET.parse("cadena.xml")
  14.  
  15. ns = {"cfdi":"http://www.sat.gob.mx/cfd/3"}
  16. print("-------------------------")
  17. #---------------------------
  18. node = d.findall("//{http://www.sat.gob.mx/cfd/3}Impuestos/[@TotalImpuestosTrasladados]")[0]
  19.  
  20. for key,val in node.items():
  21.     print(key,val)
  22.  
  23. print(node.xpath("@TotalImpuestosTrasladados")[0])
  24.  
  25. #---------------------------
  26. print("--------------------------")
  27. node = d.findall("//cfdi:Impuestos/[@TotalImpuestosTrasladados]",ns)[0]
  28.  
  29. for key,val in node.items():
  30.     print(key,val)
  31.  
  32. print(node.xpath("@TotalImpuestosTrasladados")[0])
  33.  
  34. #---------------------------
  35. print("----------------------------")
  36. E = ET.XPathEvaluator(d,namespaces=ns)
  37.  
  38. print(E("//cfdi:Impuestos/@TotalImpuestosTrasladados")[0])
  39.  
  40. [CODE]
  41. sudo perf stat -a -B -e cache-references,cache-misses,cycles,instructions,branches,branch-misses,stalled-cycles-frontend,stalled-cycles-backend,faults,migrations,L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses python main.py
  42.  

Código: [Seleccionar]
-------------------------



363104
-------------------------
('TotalImpuestosRetenidos', '1196492')
('TotalImpuestosTrasladados', '363104')
363104
--------------------------
('TotalImpuestosRetenidos', '1196492')
('TotalImpuestosTrasladados', '363104')
363104
----------------------------
363104

 Performance counter stats for 'system wide':

       124 036 315 cache-references                                             [32.68%]
         1 408 213 cache-misses              #    1.135 % of all cache refs     [33.80%]
       425 334 049 cycles                    [34.92%]
       398 416 294 instructions              #    0.94  insns per cycle       
                                             #    0.14  stalled cycles per insn [36.04%]
        98 415 633 branches                                                     [35.78%]
         2 824 985 branch-misses             #    2.87% of all branches         [34.67%]
        56 174 078 stalled-cycles-frontend   #   13.21% frontend cycles idle    [33.55%]
        56 535 015 stalled-cycles-backend    #   13.29% backend  cycles idle    [32.43%]
             2 885 faults                                                       [100.00%]
                 0 migrations                                                 
       157 605 242 L1-dcache-loads                                              [31.54%]
           915 938 L1-dcache-load-misses     #    0.58% of all L1-dcache hits   [31.54%]
         2 029 911 LLC-loads                                                    [31.54%]
           401 918 LLC-load-misses           #   19.80% of all LL-cache hits    [31.54%]

       0.355013604 seconds time elapsed


Voy a hacer lo mismo con el código que puse al inicio
Código: C
  1. #include <stdio.h>
  2.  
  3. volatile char temp0[20];
  4. volatile int  temp1[20];
  5.  
  6. int main(int argc, char **argv)
  7. {
  8.   int k,i = 0;
  9.   for( k = 0; k < 10; ++k )
  10.   {
  11.     temp0[i] = k;
  12.                 temp0[i+1] = k +1;
  13.                 temp1[i] = k;
  14.                 temp1[i+1] = k +1;
  15.                 i = i +2;
  16.   }
  17. }
  18.  
  19.  

Código: [Seleccionar]
Performance counter stats for 'system wide' (10000 runs):

           350 010 cache-references                                              ( +-  0.84% ) [79.77%]
            15 870 cache-misses              #    4.534 % of all cache refs      ( +-  0.70% ) [98.15%]
         2 486 998 cycles                     ( +-  0.86% ) [99.14%]
         1 055 928 instructions              #    0.42  insns per cycle       
                                             #    0.01  stalled cycles per insn  ( +-  0.93% ) [99.31%]
     <not counted> branches               
     <not counted> branch-misses           
     <not counted> stalled-cycles-frontend
     <not counted> stalled-cycles-backend 
               155 faults                                                        ( +-  0.01% ) [99.98%]
                 0 migrations                                                 
     <not counted> L1-dcache-loads         
     <not counted> L1-dcache-load-misses   
     <not counted> LLC-loads               
     <not counted> LLC-load-misses         

       0.000976747 seconds time elapsed                                          ( +-  0.89% )

Código: C
  1. #include <stdio.h>
  2.  
  3. volatile char temp0[20];
  4. volatile int  temp1[20];
  5.  
  6. int main(int argc, char **argv)
  7. {
  8.     int k,i = 0;
  9.     for(k=0; k < 20; ++k)
  10.         {
  11.                 temp0[k] = k;
  12.                 temp1[k] = k;
  13.         }
  14. }
  15.  
Código: [Seleccionar]
Performance counter stats for 'system wide' (10000 runs):

           357 266 cache-references                                              ( +-  0.83% ) [78.56%]
            16 297 cache-misses              #    4.562 % of all cache refs      ( +-  0.72% ) [98.56%]
         2 557 624 cycles                     ( +-  0.84% ) [99.31%]
         1 096 564 instructions              #    0.43  insns per cycle       
                                             #    0.01  stalled cycles per insn  ( +-  0.97% ) [99.34%]
     <not counted> branches               
     <not counted> branch-misses           
     <not counted> stalled-cycles-frontend
     <not counted> stalled-cycles-backend 
               155 faults                                                        ( +-  0.01% ) [99.98%]
                 0 migrations                                                 
     <not counted> L1-dcache-loads         
     <not counted> L1-dcache-load-misses   
     <not counted> LLC-loads               
     <not counted> LLC-load-misses         

       0.001006972 seconds time elapsed                                          ( +-  0.88% )



Por lo general este es el comportamiento, pero no nos vayamos con la finta, ya que al final, en este caso, estamos a merced de un kernel que controla el acceso a memoria y el flujo de nuestros programas.


 

anything