Быстрый ARM NEON memcpy

Я хочу скопировать изображение в kernel ​​ARMv7. Наивная реализация – вызов memcpy на строку.

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

Я знаю, что следующее

 d, dp, s, sp, w 

все 32-байт выровнены, поэтому моя следующая (еще очень наивная) реализация была

 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; } 

Это было на ~ 150% быстрее, чем memcpy на большом количестве итераций (на разных изображениях, поэтому не используя кеширование). Я чувствую, что это должно быть нигде рядом с оптимальным, потому что я еще не использовал предварительную загрузку, но, когда я это делаю, мне кажется, что я могу сделать производительность значительно хуже. У кого-нибудь есть понимание?

У этого ARM есть замечательная технология.

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

Ваша производительность, безусловно, будет меняться в зависимости от микроархитектуры, примечание ARM относится к A8, но я думаю, что это даст вам приличную идею, а резюме внизу – отличное обсуждение различных плюсов и минусов, выходящих за frameworks только регулярные числа, например, какие методы приводят к наименьшему количеству использования регистра и т. д.

И да, как упоминает еще один комментатор, предварительная выборка очень сложна для правильной работы и будет работать по-разному с разными микроархитектурами, в зависимости от того, насколько велики кеши и насколько велики каждая строка и куча других сведений о кэше дизайн. Если вы не будете осторожны, вы можете обрушиться на нужные вам строки. Я бы рекомендовал избегать его для переносного кода.