Messages in this thread | | | Date | Sat, 21 Nov 1998 19:09:50 -0800 | From | David Hinds <> | Subject | Re: Linux-asm: a better mousetrap?? |
| |
I've modified Richard's original benchmark a bit to make it easier to interpret. I removed the RDTSC calls since they can be trouble on SMP and non-Pentiums. I use clock() to measure CPU time instead of SIGALRM. And I rewrote the outer loop of the benchmark to demonstrate memory heirarchy effects. I also added code to flush the instruction cache prior to each checksum calculation, to measure I-cache effects, and I report results as memory bandwidths, in MB/sec.
Finally, I replaced Richard's simple but fairly slow C code with two variants. One is C plus inline asm; the other is pure C, but uses "long long" arithmetic to avoid partial register stalls in Richard's algorithm.
My C+asm checksum is significantly faster than Richard's on a 486 (due to cache pressure, I think). It is 10-25% faster on a Pentium, depending on where packets are in the memory heirarchy, due to better instruction scheduling in my code. It is 1-5% slower on Pentium II and Pentium Pro processors, due to extra loop overhead. Reordering the main loop can improve Pentium main-memory performance another 25% but hurts on PPro/PII systems, so I didn't include it.
If I flush the instruction cache before each checksum invocation, my code is not seriously impacted, but Richard's code runs significantly slower. On a Pentium or Pentium II, my code is now twice as fast: on a PPro, it is "only" 10-25% faster, thanks to the PPro's full-speed secondary cache.
Richard could modify his code to use my instruction sequence to get the Pentium scheduling benefit. I'm not familiar enough with the PPro/PII architecture to know if there are better ways of coding this to reduce pipeline stalls. On the 486, however, Richard's code will always lose, because of its small cache. Richard's main "innovation" (fully unrolling a 512-iteration loop) has a best-case performance advantage of 5% in the case where the checksum code is always in the primary I-cache, but is significantly slower on all platforms whenever the code is not in primary cache. In real life, one would not expect the TCP checksum to always be in primary cache, especially if it is Richard's code, which occupies a full 50% (4K) of the 8K I-cache on a PPro or PII.
My better straight-C checksum using "long long" arithmetic is on the order of 20% slower than my C+asm code under all test conditions. It performs better than Richard's code in the instruction-cache-flush test on most platforms. That's not a huge win for assembly...
I'm still not completely happy with this benchmarking framework, despite my efforts to separate out I-cache, D-cache, and level 2 cache effects. There are still some performance anomolies in the results (though I don't think they affect the algorithm comparison). I did all my tests with regular gcc-2.7.2.3 and "-O2".
My chksum.c replacement is available at
ftp://csb.stanford.edu/pub/pcmcia/extras/chksum.c
and Richard's original package is at:
ftp://boneserver.analogic.com/pub/downloads/linux/linux-asm.tar.gz
In my chksum.c, to enable or disable the I-cache flush, change the '#define FLUSH' line. To flip between my C+asm or straight-C algorithms, you need to change the '#if 1' line to '#if 0'.
Bottom line: Richard's code is not a good idea.
-- Dave Hinds
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |