3 ms·
I don't see how you can write an article on x86 memcpy without having benchmarks for 'rep movs' as a baseline. That is the old x86 assembly instruction that doe
by wscott 10y ago
I don't see how you can write an article on x86 memcpy without having benchmarks for 'rep movs' as a baseline. That is the old x86 assembly instruction that does the entire copy in one instruction. With modern processors, that instruction drops into a microcode loop to move the data using the internal instructions.
Microcode has a bit of a delay getting in there and so 'rep movs' is not so great for short moves, but normally does pretty well for large transfers.
That is the big problem with memcpy, the optimal code depends on how it is used. Block copies of large aligned structures wants different code than moving short unaligned strings. Ideally, the compiler has more context and can select the different versions for different call sites.
- bboreham 10y agoIf you use more registers as storage it can go faster. 'rep movs' uses no registers for storage; only source, destination and count. There are many, many tricks like doing 'look ahead' to start the L1 cache bringing in the next line before we actually need it, to hide that latency. And the article describes how there are various code paths for big blocks, short blocks, aligned, unaligned, etc.
- mikeash 10y agoThe hardware can do whatever it wants as long as it preserves the semantics. I'm sure modern CPUs use registers and perform prefetching as appropriate when they encounter a rep movs.
- masklinn 10y agoSurely the CPU hardware isn't limited to the ABI either and microcode can directly work on the physical registers?
- mikeash 10y agoIndeed. It could even conceivably use some special memcpy hardware. I doubt it goes that far, but another comment here mentions that it will use SSE or AVX registers when appropriate. `rep movsb` shouldn't be thought of as repeatedly copying single bytes from source to destination, but rather as a `memcpy` instruction with a weird name due to history. If it's used frequently enough to be worth optimizing (and it seems like it is) then Intel and AMD can easily recognize it as such and make their hardware perform the operation as efficiently as possible.
- deleted 10y ago[deleted]
- fsfod 10y agoI remember Andy Glew discussing a little bit of the history of the behaviour of REP MOVS microcode in the comments of this stack overflow question http://stackoverflow.com/questions/8858778/why-are-complicated-memcpy-memset-superior/9177369#9177369 http://stackoverflow.com/questions/8858778/why-are-complicat...
- wscott 10y agoYup, we spend a bunch of time trying different options. But they never gave Andy the uop he really wanted which would zero the next cache line. Normally when you start writing to memory the machine will populate the cache line to be written from memory. He wanted the ability to say he plans on writing the whole thing so don't bother and if something happens then assume it is all zeros. (or something like that) Perhaps the current machines have this now... but probably not.
- tedunangst 10y agoAmong other problems with benchmarking SSE versions, your operating system may implement lazy FPU save/restore. SSE memcpy suddenly turns every process into an FPU using process, increasing context switch overhead. This is something you won't see in single process microbenchmarks.
- pcwalton 10y agoAre there many processes out there that don't use SSE these days? LLVM, for example, will aggressively use SSE for memcpy/memmove of medium sized values (e.g. copies of 128 byte long structs), which almost every nontrivial app will end up using at some point. Likewise, if the autovectorizer succeeds even once, then you'll also end up using SSE.
- tedunangst 10y agoTrue. I'm still living in the Bronze Age, but we may already be past the tipping point. I wonder if any consideration was given. Personally I don't know what the cost is, but I know I've never seen anybody try to measure it.