Converting Array of Floats to UINT8 (`char`) or UINT16 (`unsigned short`) Using SSE4
why not load 4 packed __m128 and then store 32 Pixels at once


I think that's 16 pixels, but it's a good plan. The pack instructions were used inefficiently (in the linked question that was not really an issue) and that would be improved by processing more elements simultaneously. For example, something like this:

#define SSE_STRIDE 16

void ConvertToUint8(char* mO, float* mF, float* mB, unsigned numRows, unsigned numCols, unsigned numColsPad, float scalingFctr)
{
    unsigned ii, jj;
    __m128 a, b, c, d;
    __m128i ai, bi, ci, di, p0, p1;
    __m128 scalingFactor = _mm_set1_ps(scalingFctr);
    float *inptr;
    __m128i *outptr;

#pragma omp parallel for private(jj, a, b, c, d, ai, bi, ci, di, p0, p1, inptr, outptr)
    for (ii = 0; ii &lt; numRows; ii++) {
        inptr = &amp;mB[ii * numColsPad];
        outptr = (__m128i*)&amp;mO[ii * numColsPad];
        for (jj = 0; jj &lt; numCols; jj += SSE_STRIDE) {
            a = _mm_loadu_ps(inptr);
            b = _mm_loadu_ps(inptr + 4);
            c = _mm_loadu_ps(inptr + 8);
            d = _mm_loadu_ps(inptr + 12);
            inptr += SSE_STRIDE;
            ai = _mm_cvtps_epi32(_mm_mul_ps(a, scalingFactor));
            bi = _mm_cvtps_epi32(_mm_mul_ps(b, scalingFactor));
            ci = _mm_cvtps_epi32(_mm_mul_ps(c, scalingFactor));
            di = _mm_cvtps_epi32(_mm_mul_ps(d, scalingFactor));
            p0 = _mm_packs_epi32(ai, bi),
            p1 = _mm_packs_epi32(ci, di);
            p0 = _mm_packus_epi16(p0, p1);
            _mm_storeu_si128(outptr++, p0);
        }
    }
}


I've also changed some thing to unsigned, because some useless sign-extension was going on sometimes (depending on how it was compiled). inptr and outptr are now calculated outside the inner loop, normally we can expect the compiler to be pretty clever about that too but compiling with OpenMP support seemed to make Clang less clever, it put the actual multiplication between ii and numColsPad inside the inner loop. That's not good, because on Intel that imul would go to p1, and p1 is already completely packed with the float-to-int conversions and fp-multiplications (eg on Skylake both of those go to p01). That loop should be able to run at 1 iteration every 4 cycles in the best case on most architectures, but with that extra imul in there that wouldn't be possible.

To convert to uint16 something similar can be used, but with _mm_packus_epi32 and no packing to bytes.