5 ms·
I'm trying to understand speculative execution. Given this int result = foo != bar ? do_side_effect_and_return() : safe_return(); C code, am I right to a
by cm3 11y ago
I'm trying to understand speculative execution.
Given this
int result = foo != bar ? do_side_effect_and_return() : safe_return();
C code, am I right to assume both functions will be executed speculatively?
What other potential bugs/gotchas are lurking with speculative execution?
- daemin 11y agoIn the context of a CPU, especially one with a deeper pipeline, the comparison value will only be known at some stage deep within the pipeline. Therefore to not stall the pipeline until the result is known, the CPU will start to execute either one of the branches. Then once the value is known, if it guessed the branch correctly it will continue executing as normal, having already partially executed it. But if it guesses incorrectly it has to flush the work that it has done and start executing the branch not taken. Edit: One particular thing to note is that side effects that occur within the pipeline do not actually occur until the latter stages of the pipeline, where the writes to memory and registers are realised. By that stage the condition result would already be known and the correct branch would be executing within the processor.
- cm3 11y agoYeah, but what if do_side_effect_and_return() deletes file. This surely cannot be prevented. What I'm mostly wondering is how it is that half of our code doesn't break all the time due to speculative execution. I'm looking for an explanation how it's prevented or if it's just careful luck because compiler and runtime writers took precautions.
- panic 11y agoThe CPU won't speculatively execute past certain instructions. AFAIK it's up to (e.g.) the SSD driver to prevent the CPU from speculatively sending commands to the drive.
- gliptic 11y agoIt's not up to the SSD driver. The SSD driver will not see any effects of speculatively executed code and there's no way the CPU could speculatively send commands to the drive.
- panic 11y agoWhat if you're communicating with the SSD via DMA? Don't you have to make sure that the writes aren't speculatively executed?
- daemin 11y agoBecause DMA occurs when the CPU writes to memory, and as my comment above states this occurs after the condition is evaluated and the jump instruction (not) taken. Speculative execution is purely within the CPU and doesn't leak out - except in the case of worse than ideal performance.
- daemin 11y agoOk, from what I see you are thinking at too high a level for this. The CPU has a pipeline where it executes instructions. This pipeline has stages in it for: fetching the instruction from L1 cache (a), decoding the instruction (b), fetching data from registers or memory (c), computing the instruction (d), storing the data back into registers or memory (e). This is a rough grouping of these stages, and each of these (a-e) stages is comprised of smaller stages, one of which executes in each clock cycle. So between the first stage where a CPU starts executing a comparison instruction (a), and when it knows what the value is (d) that can be many clock cycles. So instead of waiting and stalling it instead guesses which branch will be taken and starts feeding it in. It is only in stage (e) where it stores values to registers or memory where actions can actually take place, and by the time it gets there it is executing the correct branch. Either because it guessed the correct branch from the beginning or it has mispredicted, flushed the pipeline, and is now executing the correct branch. Edit: Note that there is no such instruction as "delete file on SSD". The CPU has various ways of working with external devices (such as sounds/video chips, ssd's, etc), with memory mapping being one of the more popular one, but there's also IO pins and a variety of hardware protocols that it can write instructions to use. If you want to learn up on this get a small device like a Raspberry Pi and play around.
- cm3 11y agoI see, are CLWB and PCOMMIT for NVME safe?
- vardump 11y agoYes. They're no exception. They actually make DMA transfer safe, without doing unnecessary work.
- cm3 11y agoSo all this speculative business is more about using idle bits of the chip to warm it up for either branch to be taken, thereby reducing some of the time for that code to execute, but any and all op that would actually modify memory or access stuff on the bus is exempt from speculation. About right?
- pjc50 11y agoFirstly, the article doesn't mention speculative execution - it refers to a programming technique which is effectively (assume f,g,h are arithmetic functions, not 'program' functions): compute f while f is in the pipeline, compute g while g is in the pipeline, compute h let bits = 111111..111 if h is true or 00000...000 if h is false let result = (f & bits) | (g & ~bits) In your example, if they're function calls, and not inlined, then they won't execute speculatively at all: speculative execution usually only applies to straight-line instructions and in any case only applies to letting the instruction go off into an "execution" unit. Only one branch should ever make it into the "commit" phase of the pipeline (think like a database commit), and only one should ever have effects that are visible off the processor die. Also things like system calls, interrupts, context switches, and so on tend to flush the pipeline and insert a "barrier", at which point all the instructions before the barrier have committed and none of the ones after the barrier have committed.