4 ms·
how exactly do you use a fraction of a cycle? i would assume that it would be fractional on average, but then again I can't exactly speak for my expertise on ho
by ozzmotik 8y ago
how exactly do you use a fraction of a cycle? i would assume that it would be fractional on average, but then again I can't exactly speak for my expertise on how instructions map to cycles and if it's solely an integer mapping
- kizer 8y agoI believe he means on average, as you said.
- mcguire 8y agoYou handle multiple bytes at once; it's fractional on average. He's using vectorized operations to handle 16 bytes at a time, basically: __m128i has_error = _mm_setzero_si128(); __m128i zero = _mm_setzero_si128(); for (...) { __m128i current_bytes = _mm_loadu_si128(src); has_error = _mm_or_si128(has_error, _mm_cmpgt_epi8(zero,current_bytes)); } return _mm_testz_si128(has_error, has_error); Each of the _mm* "functions" becomes 1 (?) vector instruction.
- dragontamer 8y ago> I can't exactly speak for my expertise on how instructions map to cycles and if it's solely an integer mapping 1. Standard ALUs on modern processors are 64-bits at a time. So right there, you're 8x faster on a per-byte basis. 2. He's using vectorized operations, so he can work with 128-bits, 256-bits (or potentially even 512-bits on high-end processors like Skylake-X). So 16x, 32x, or 64x at a time per operation. 3. Modern processors are super-scalar with multiple ALUs and multiple execution ports. I forget what the precise theoretical limit is, but Intel AND AMD machines can execute something like 4 or 5 operations per clock, depending on circumstances. That assumes that all operations have been decoded into micro-ops (uops), they fit inside the uop cache (think of a uop cache as a L0 cache: beyond even the L1 cache), that they perfectly line up to available execution ports, that your data has no dependencies, and a whole host of other conditions. But its theoretically possible. --------- In practice: your code will be limited by memory (even L1 cache is slower than the CPU), by decoding speed (not everything fits in the uOp cache, and only loops really benefit from the uop cache), dependencies (a = x + 1. a = a+2. The 2nd instruction depends on the 1st one to execute first, so the two instructions can't be done in parallel / superscalar). The CPU is pretty good at trying to figure out how to optimally reorder and out-of-order execute your code. But that means that predicting the performance of the CPU is incredibly difficult: you have to keep in mind all of the parts of the CPU while thinking of the assembly code.