Performance von memcpy
-
Hallo zusammen,
bisher dachte ich immer ganz naiv, memcpy würde mit ASM der CPU irgendwas magisches sagen, und die wär dann superschnell.
Da mich eben beim Optimieren mein Profiler jedoch drauf hingewiesen hat, habe ich mal getestet:#include <iostream> // CAUTION! Works only if ( (bytes%4) == 0 ). void* MyMemcpy( void* dest, void* src, size_t bytes ) { int* srcStart = (int*)src - 1; int* destStart = (int*)dest - 1; int* srcEnd = (int*)src + (bytes >> 2); for (; srcStart < srcEnd; ) *(++destStart) = *(++srcStart); return dest; } int main() { const size_t memSize( 10000000 ); unsigned char* mem1( new unsigned char[memSize] ); unsigned char* mem2( new unsigned char[memSize] ); std::cout << "memcpy start\n"; for ( int i( 0 ); i < 1000; ++i ) memcpy( mem2, mem1, memSize ); std::cout << "memcpy end\nMyMemcpy start\n"; for ( int i( 0 ); i < 1000; ++i ) MyMemcpy( mem2, mem1, memSize ); std::cout << "MyMemcpy end\n"; delete[] mem1; delete[] mem2; }Auf meinem Rechner (Core i5) ist MyMemcpy nur ca. 20% langsamer als memcpy. Ist mein Compiler (VC++ 2005, Release, speed, SS2 usw.) doof, kann meine Hardware irgendetwas nicht, oder ist bei euch memcpy auch nicht so viel dramatisch schneller?
Gruß
Dobi
-
ist MyMemcpy nur ca. 20% langsamer
20% ist viel. Was hast du erwartet? Btw. Deine Implementation funktionier nur fuer Vielfache von 4.
-
Stimmt natürlich, danke für den Hinweis. Habs direkt reineditiert, damit nicht irgendwann mal irgendwer drüber stolpert.
Ich hatte halt gedacht, dass man modernen Prozessoren die drei Adressen in bestimmte Register legt, dann den magic_turbo_memcpy-Befehl absetzt und die Post abgeht. Post im Sinne von "um ein Vielfaches schneller". Scheint ja aber nicht so zu sein.
-
Hat mich auch gewundert, als ich das vor etwas längerer Zeit mal getestet habe. Sollte so ein 128bit-optimiertes memcopy nicht auch ~4 mal schneller sein, als ein 32 bit memcpy?
-
Sollte so ein 128bit-optimiertes memcopy nicht auch ~4 mal schneller sein, als ein 32 bit memcpy?
Der Speicher wird nicht schneller dadurch. Insbesondere jeder Cache Miss der dann zu einem Zugriff auf den Hauptspeicher führt bremst die CPU massiv aus.
-
Ihr meint sicher das Code-Snippet von AMD.
void nontemporal_copy(char* outbuff, char* inbuff, int size) { const int step = 64; // cache line while(size > step) { _mm_prefetch(inbuff + 320, _MM_HINT_NTA); // non-temporal prefetch __m128i A = _mm_loadu_si128((__m128i*) (inbuff + 0)); __m128i B = _mm_loadu_si128((__m128i*) (inbuff + 16)); __m128i C = _mm_loadu_si128((__m128i*) (inbuff + 32)); __m128i D = _mm_loadu_si128((__m128i*) (inbuff + 48)); // destination address must be 16-byte aligned! _mm_stream_si128((__m128i*) (outbuff + 0), A); _mm_stream_si128((__m128i*) (outbuff + 16), B); _mm_stream_si128((__m128i*) (outbuff + 32), C); _mm_stream_si128((__m128i*) (outbuff + 48), D); inbuff += step; outbuff += step; size -= step; } _mm_mfence(); }Non-Temporal bedeutet, dass die geschriebenen Daten nicht in den CPU-Cache geladen werden. Das beugt Cache-Trashing vor.
Aber nur weil es 128bit breite Daten verwendet, ist es noch nicht 4mal so schnell wie memcpy.Hab gegenüber standard-memcpy aber einen deutlichen Performance-Vorteil gemessen.