6 ms·
SIMD in the 90s: Programming Intel's Pentium MMX
- Const-me 2mo agoI would add than SSE1 and SSE2 are now required parts of AMD64 instruction set. All 64-bit PC processors are required to support them both. For that reason, modern compilers are ignoring x87 FPU when building 64-bit binaries. Instead, they compile all float and double arithmetic into SSE1 and SSE2 instructions, respectively.
- grg0 2mo agoWhich is not to say that they are necessarily auto-vectorizing. You know wassup when you see vaddsd instead of vaddpd. And ideally you'd use AVX-512 to saturate a modern cache line if you can afford to drop support for the older devices.
- spider-mario 2mo agoOr runtime CPU detection and dispatch to support both.
- hbogert 2mo agoolder devices, is rather vague, this means intel client chips even as late as panther lake do not support avx512 or avx10
- icelusxl 2mo agoCompilers like GCC and Clang treat C's "long double" type by default as 80-bit wide and result in x87 generated code. This can be overridden to use either 64-bit or 128-bit floating point values.
- theandrewbailey 2mo agoTake a look at the micro-architecture levels. x86-64-v1 contains all the instructions that the original AMD64 and compatible Intel CPUs supported. v2 is all the SSE levels, v3 is AVX and AVX2, v4 is AVX-512. https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels https://en.wikipedia.org/wiki/X86-64#Microarchitecture_level...
- chasil 2mo agoThe wiki says: "Additional XMM (SSE) registers: Similarly, the number of 128-bit XMM registers (used for Streaming SIMD instructions) is also increased from 8 to 16... "The original AMD64 architecture adopted Intel's SSE and SSE2 as core instructions." https://en.wikipedia.org/wiki/X86-64 https://en.wikipedia.org/wiki/X86-64 This wansn't v2?
- VorpalWay 2mo agoNot sure what your question is. I dont see any contradiction with the parent comment. SSE went to version 4.2 (it gets complicated in the numbering and even naming). Only 1 and 2 were included in the base 64-bit ISA.
- jcranmer 2mo agox86-64 mandates SSE2 as a minimum requirement because it uses the SSE registers in the ABI for implementing float (which requires SSE) and double (which requires SSE2) arithmetic. (The x87 unit, which is what the 32-bit x86 ABI uses, can only do extended-precision arithmetic, which causes a whole heap of problems). Because it's so thoroughly integrated in the ABI, v1 has to have a min-SSE2 requirement. Subsequently, there were additional instructions added in SSE3, SSSE3, SSE4.1 and SSE4.2, which are all incorporated into the v2 ISA level (along with a few other instructions). Then all of these instructions were given 256-bit variants in AVX, and AVX2 adds some more vector instructions; these are incorporated into the v3 ISA level. And then along comes AVX-512 and naming just becomes a podge at that point...
- wbl 2mo agoExtended double has some niche and quite useful for its application properties. You can for instance simulate 128 bit floats more easily with it.
- dfox 2mo agoThey were always required. IIRC early AMD64 CPUs did not support x87 instructions in long mode at all (causing #UD), and that support was Intel's extension in first EM64T CPUs.
- 45t345tg35 2mo agoPlease refrain from making things up -- Long Mode has always supported x87. You may be mis-remembering LAHF/SAHF.
- balou23 2mo agoLAHF and SAHF are an interesting rabbit hole themselves. If you ever dug into x86 assembler programming... at first they make no sense at all. They only save/restore a tiny part of the available flag registers. The mnemonics themselves make little sense - load/store are not really used in any other base x86 mnemonics (unlike e.g. 6502 mnemonics, which use LD?/ST? instead of MOV like x86). It only clicked when I read an Intel document about porting assembler code from the 8080 to the 8086. LAHF/SAHF are basically convenience instructions to make porting easier. Many 8080 instructions did not alter the flags, unlike their 8086 counterparts. Substituting an `INX` instruction with `LAHF; INC; SAHF` made it possible to mechanically translate assembler source code. And yeah, 8080 mnemonics had LDA and STA like the 6502...
- whizzter 2mo agoAnother large part of using SSE for floating point arithmetic today is that while the floating point stack was very good for code-density (I still use older compilers for size-optimized C code for demoscene intros), it was also quite painful in being stateful. This is a large part of why "floating point to integer conversion is slow" cargo culting came from (probably disappeared today but was often seen back in the day). Many x86 standard libraries emitted code that first set the floating point rounding mode before the storing conversion, you could use a /QIfist compiler option on MSVC to omit that but if you were unlucky to call some code that fiddled with the rounding mode your code would become unreliable (iirc unfortunally that did include some old D3D or OGL version). With SSE iirc it's separate instructions for different rounding instead of a FPU mode.
- ack_complete 2mo agoI did extensive MMX and SSE2 optimization of audio and video codecs in the 2000s. MMX made a large difference, but it was a pain. MMX optimization practically required assembly language. The Pentium MMX was an in-order dual pipe CPU, and while compilers supported MMX intrinsics, their code generation for it was abysmal. Visual C++ 6, for instance, would emit code that was 2/3rds register-to-register moves, with values being unnecessarily moved between two registers between each ALU op. This was also a problem with SSE/SSE2 intrinsics. The worst case I saw was the _mm_set_epi8() intrinsic, which was used to construct a 128-bit vector from 16 inputs. When used with all constants, it should have generated a single 128-bit constant load; instead, Visual Studio 2008 generated ~80 instructions to compute it from byte loads. Microsoft didn't fix it until VS2010. The latency of MMX instructions combined with the in-order dual pipe architecture also made asm loops messy. Simple ops were single-cycle, but multiplies had 3 cycle latency, stores required data an additional cycle in advance, and computed load/store addresses were also needed a cycle in advance. Simply running 2-4 iterations in parallel wasn't an option as there were only 8 vector registers and you'd still get bottlenecks on functional units. Getting peak performance thus often required interleaving loop iterations with special entry and exit code around the loop. The issue with EMMS is understated. When the CPU switched to MMX, it marked the entire x87 stack as full. If you forgot the EMMS instruction, it wasn't just some strange floating-point bugs that would happen -- the next few x87 floating point calculations could just outright produce NaNs due to FP stack overflow. Furthermore, as these NaNs propagated, the CPU required microcode assists to handle them. So, even if the program didn't crash, an entire calculation domain would get poisoned and slow down by ~20x. Ultimately, I don't think SSE2 was what killed MMX, but rather SSE, and specifically floating point. MMX not only didn't support floating point, but was also highly concentrated on 16-bit signed integers and secondarily 8-bit unsigned integers. Support for 32-bit integers was particularly lacking and pack/unpack conversions were a bottleneck. Trying to do 3D was cramped because doing so required fixed-point and MMX didn't have the same affordances as DSPs or NEON for rounding or implicit narrow/widen in operations, or even swizzles. SSE, on the other hand, was just straight floating point with standard automatic IEEE rounding and also had important added operations like swizzles and insert/extract. Thus, when 3D took off, SSE was far more useful than MMX. MMX, however, still remained useful for a while for image and signal processing. SSE2 being twice as wide didn't help algorithms that couldn't use the greater width, such as 8x8 block motion prediction. Additionally, some CPUs at the time only had a 64-bit data path and had to split SSE2 ops, but because of their 4-1-1 decode template, could only decode one such instruction per cycle. The result was that code using the MMX registers could still run noticeably faster than with the SSE registers. This caused some confusion with the 64-bit version of Windows since Microsoft tried to say that x87/MMX shouldn't be used in long mode, but after queries from video processing companies had to document that the x87/MMX registers were enabled and context switched for user mode code.
- nojokepoke 2mo agoWhat’s often overlooked is that adoption of MMX was slooooow. Intel compiler were the only intrinsic data types for years. The big win was DirectX 3 audio drivers that used premade Intel libraries. It took at least five to ten years for SIMD to catch on, but the never stopped Intel from evolving it. Then they lost the GPU wars lol rip larabeee.
- ack_complete 2mo agoMMX had heavy adoption in image and video processing. IDCT, motion prediction/compensation, YUV/RGB conversion, and alpha blending all benefited from it.
- nojokepoke 2mo agoThanks for the reminder. Yes Intel was touting high bit rates in software compared to the matrox millennium hardware 2d accelerator.
- p_l 2mo agoAnd now the legacy of Larrabee, AVX-512, is only properly available on AMD for consumers :D
- theandrewbailey 2mo ago> Each MMX register is 64 bits wide. Internally, the MMX registers were aliases of the x87 floating-point registers. Due to the way the first Pentium 3 CPUs (Katmai) were built, they likewise aliased the x87 (and thus, MMX) registers to the XMM SSE registers, but this was hidden from programs. It wasn't until at least the Coppermine revision that they were separate registers again.
- Nition 2mo agoI remember hearing a rumour as a young teen that the Coppermine codename meant it actually had copper wiring and that's what made it faster somehow. Copper has lower resistance than aluminium and can therefore help chips run faster - it makes sense! But it was just a codename and the coppermine had aluminium interconnects. My family got a PIII 533Mhz coppermine, in the early sideways Slot 1 configuration. Blazing fast at the time. Been a long time since I heard anyone say "coppermine". CPU progress was wild in the 90s, where you could wait two years and your new CPU would be double the old one's speed at the same price point. Today it takes near a decade for CPU speed to double. I also recall the first game that advertised its exciting use of the new MMX technology: POD.[1] [1] https://en.wikipedia.org/wiki/POD_(video_game) https://en.wikipedia.org/wiki/POD_(video_game)
- Lerc 2mo agoCopper interconnects might have been introduced around then, but I suspect the naming is more coincidental than anything. I remember just after IBM got copper interconnects working, there was a stock market dive, I ranted to my partner about how crazy it is for a company to achieve a sought after goal and have its value decrease. The next day there was a news story about the entire market decline being stalled by the force of IBM buying back it's own shares. My partner told me I should rant less and invest more.
- Nition 2mo agoHaha, yeah the rumour came around at a time when there was real work going on with copper interconnects which just confused the situation, but the coppermine didn't use them.
- gustavopezzi 2mo agoAuthor here. Thanks for sharing.
- ColdStream 2mo agoWhen MMX first came out and there were games that supported it, many reviewers were convinced that it improved 3D performance. As far as I could tell, it wasn't really used for 3D and that the only enhancement was to the audio system. But the placebo effect of "If has MMX thus its better" did stick around for a long while. An aside, but when SSE came a long that was a real big leap in 3D performance, just as GPU's started to gain some independence. So in about 2010, I tried to fire up Turok 2 just to see how fast it would run on a then modern CPU/GPU setup. It couldn't crack 200fps, however games only a year or two later would fly way past that. Turok 2 came out just before SSE and thus basically ran in purely x86/x87 space, thus the performance gap.
- jamesu 2mo agoAFAIK, MMX was more for fixed point math (as also pointed out by another commenter) which would explain why it wasn't used much for 3D. You tended to see it more in image and sound processing code. Maybe the reviewers got it mixed up with 3DNow.
- ack_complete 2mo agoMMX did help significantly with software 3D rendering. I worked on a software rasterizer that benefited significantly from it. But it didn't take long before even a well-optimized software renderer on a high end CPU couldn't keep up with a low end GPU on a low end CPU.
- ColdStream 2mo ago[dead]
- pseudohadamard 2mo agoGo to page. Nothing. Enable Javascript for it. Still nothing. Enable more Javascript. Still nothing. Third lot of Javascript and now it finally renders. It's static text with a few images... that doesn't display until you tell NoScript to enable Javascript from a pile of third-party sites.
- gustavopezzi 2mo agoIt's probably the syntax highlight JS I'm using for the code snippets.
- kristianp 2mo agoEnjoying the "DOS" font of the code examples. The wikipedia page on the Pentium has multiple references to an Intel publication called "Solutions", May/June 1993. It would be interesting to see that, but can't find a copy. https://en.wikipedia.org/wiki/Pentium_(original)#cite_note-18 https://en.wikipedia.org/wiki/Pentium_(original)#cite_note-1...
- LoganDark 2mo agohttps://int10h.org/oldschool-pc-fonts/readme/ https://int10h.org/oldschool-pc-fonts/readme/
- danparsonson 2mo agoWow thank you for that - I can almost hear the 40MB HDD purring quietly in the background
- 45t345tg35 2mo agoI have looked -- no luck so far. I will keep looking...
- kristianp 2mo agoThere are some posts on https://www.cpu-world.com/forum/viewtopic.php?p=330329 https://www.cpu-world.com/forum/viewtopic.php?p=330329 , however the images are not visible. I tried registering, but it says "bot registration detected".
- LoganDark 2mo agoSame here. Not sure what qualifies as a non-bot but it's apparently not me.
- tgma 2mo agoMany cheap modems ("WinModem") had drivers that did DSP logic on the system CPU as opposed to their board relied on MMX.
- Panzerschrek 2mo agoJohn Carmack promised that Quake II will use MMX, but this wasn't done. That's why software rendering in Quake II is so boring, it doesn't even support colored lighting. In the other hand Unreal did use MMX, which allowed it to work in 32-bit color mode with colored lighting and a bunch of other effects.
- krige 2mo agoIME Q2 also ran much slower on comparable hardware despite looking worse. The first rig I played them on was an unaccelerated P200MX with a paltry 32 megs of RAM and Q2 struggled at 320x240 while Unreal was slightly choppy but acceptable at 400x300. Good lord, 400x300.
- KellyCriterion 2mo agoMh, QuakeII without hardware rendering was nearly unplayable :-))
- fenestella 2mo ago[flagged]
- kstenerud 2mo agoI still remember the MMX TV campaign they put out in the 90s. https://www.youtube.com/watch?v=5zyjSBSvqPc https://www.youtube.com/watch?v=5zyjSBSvqPc https://www.youtube.com/watch?v=cnEuWfFTuxg https://www.youtube.com/watch?v=cnEuWfFTuxg I was watching this and thinking "Who's going to even understand what this is about? Why is this playing on primetime TV?" Playing video on a computer wasn't a thing at the family consumer level at this time, and gaming was still a geeky niche.
- hbogert 2mo agoThey were buying mindshare, not gonna lie, i was only 10 back then and i instantly knew that intel has got to be better than all the others because they have MMX right?!..
- thisguylikesai 2mo ago[flagged]