#include #include /** Функция memcpy может работать неоптимально при выполнении одновременно следующих условий: * 1. Размер куска памяти сравнительно небольшой (как правило меньше, приблизительно, 50 байт). * 2. Размер куска памяти неизвестен во время компиляции. * * В этом случае, она работает неоптимально по следующим причинам: * 1. Функция не инлайнится. * 2. Тратится много времени/инструкций на обработку "хвостиков" данных. * * Существуют ситуации, когда функцию можно сделать быстрее, воспользовавшись некоторыми допущениями. * Одно из таких допущений - возможность читать и писать какое-то количество байт после конца соответствующих диапазонов памяти. * Тогда можно не тратить код на обработку хвостиков, а выполнять копирование всегда большими кусками. * * Эта ситуация является типичной, например, когда короткие куски памяти копируются подряд в один непрервыный кусок памяти * - так как каждое следующее копирование будет перетирать лишние данные от предыдущего копирования. * * Допущение о том, что размер небольшой, позволяет нам не разворачивать цикл. * Это работает медленее, когда размер, на самом деле, большой. */ inline void memcpySmallAllowReadWriteOverflow15(char * __restrict dst, const char * __restrict src, size_t n) { for (size_t i = 0; i < n; i += 16) _mm_storeu_si128(reinterpret_cast<__m128i*>(dst + i), _mm_loadu_si128(src + i)); } inline void memcpySmallAllowWriteOverflow15(char * __restrict dst, const char * __restrict src, size_t n) { if (reinterpret_cast(src) % 4096 <= 4096 - 16) memcpySmallAllowReadWriteOverflow15(dst, src, n); else memcpy(dst, src, n); }