Mémoire rapide ARM NEON

Je veux copier une image sur un kernel ARMv7. L’implémentation naïve consiste à appeler memcpy par ligne.

for(i = 0; i < h; i++) { memcpy(d, s, w); s += sp; d += dp; } 

Je sais que ce qui suit

 d, dp, s, sp, w 

sont tous alignés sur 32 octets, donc ma prochaine implémentation (encore assez naïve) était dans le sens de

 for (int i = 0; i < h; i++) { uint8_t* dst = d; const uint8_t* src = s; int remaining = w; asm volatile ( "1: \n" "subs %[rem], %[rem], #32 \n" "vld1.u8 {d0, d1, d2, d3}, [%[src],:256]! \n" "vst1.u8 {d0, d1, d2, d3}, [%[dst],:256]! \n" "bgt 1b \n" : [dst]"+r"(dst), [src]"+r"(src), [rem]"+r"(remaining) : : "d0", "d1", "d2", "d3", "cc", "memory" ); d += dp; s += sp; } 

Ce qui était environ 150% plus rapide que memcpy sur un grand nombre d’itérations (sur différentes images, ne tirant donc pas parti de la mise en cache). Je pense que cela devrait être loin de l’optimum, car je n’ai pas encore utilisé le préchargement, mais lorsque je le fais, il semble que je ne peux qu’empirer les performances. Est-ce que quelqu’un a une idée ici?

ARM a une excellente note technique à ce sujet.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka13544.html

Votre performance variera certainement en fonction de la micro-architecture, la note de ARM figure sur l’A8, mais je pense que cela vous donnera une idée décente. Le résumé en bas est une excellente discussion sur les différents avantages et inconvénients qui vont au-delà de la nombres normaux, tels que les méthodes qui génèrent le moins d’utilisation du registre, etc.

Et oui, comme un autre intervenant le mentionne, il est très difficile d’obtenir des préchargements, et cela fonctionnera différemment avec différentes micro-architectures, en fonction de la taille des caches, de la taille de chaque ligne et de nombreux autres détails relatifs au cache. conception. Si vous ne faites pas attention, vous pouvez finir par rayer les lignes dont vous avez besoin. Je recommanderais de l’éviter pour le code portable.