Closed Bug 596421 Opened 16 years ago Closed 12 years ago

Loops may benefit from code alignment on x86 processors

Categories

(Core Graveyard :: Nanojit, defect)

x86
All
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED DUPLICATE of bug 867001

People

(Reporter: stejohns, Unassigned)

Details

Attachments

(2 files)

Investigating an intermittent slowdown in a particular microbenchmark TR, I found that the culprit seemed to be the alignment of the label at the top of the inner loop: if it happened to land on an odd address, the benchmark was ~25% slower than if it landed on an even address. (This was on MacPro eight-core Xeon, running x86-32 code). Some quick hackery to insert a single-byte NOP if the address was odd (thus artificially moving the loop branch label to an even address) erased the slowdown. Some cursory research leaves me a bit muddled as to what the preferred loop alignment is on x86-32 for "modern" processors, but this one anecdotal case makes me suspect that further research (perhaps by someone with more x86 assembly expertise than I) could be profitable.
More anecdotes from this extremely synthetic testcase: padding loops to 16 or 8 byte alignments made things *slower* by another 5% or so. Padding to 4-byte alignment seemed equivalent to 2-byte alignment.
The x86 code being generated by the JIT for the "slow" version: 0x5e1aff: mov -0x58(%ebp),%ebx 0x5e1b02: mov 0x14(%ebx),%esi 0x5e1b05: and $0xfffffff8,%esi 0x5e1b08: mov -0x28(%ebp),%ebx 0x5e1b0b: mov %ebx,0x10(%esi) 0x5e1b0e: mov -0x20(%ebp),%ebx 0x5e1b11: lea 0x1(%ebx),%ebx 0x5e1b14: mov %ebx,-0x20(%ebp) 0x5e1b17: mov -0x20(%ebp),%ebx 0x5e1b1a: mov %ebx,-0x5c(%ebp) 0x5e1b1d: cmp $0x186a0,%ebx 0x5e1b23: jb 0x5e1aff for the "fast" (padded) version: 0x5e1afe: nop 0x5e1aff: mov -0x58(%ebp),%ebx 0x5e1b02: mov 0x14(%ebx),%esi 0x5e1b05: and $0xfffffff8,%esi 0x5e1b08: mov -0x28(%ebp),%ebx 0x5e1b0b: mov %ebx,0x10(%esi) 0x5e1b0e: mov -0x20(%ebp),%ebx 0x5e1b11: lea 0x1(%ebx),%ebx 0x5e1b14: mov %ebx,-0x20(%ebp) 0x5e1b17: mov -0x20(%ebp),%ebx 0x5e1b1a: mov %ebx,-0x5c(%ebp) 0x5e1b1d: cmp $0x186a0,%ebx 0x5e1b23: jb 0x5e1afe
Attached patch Grotesque hack — — Splinter Review
Here's the horrific hack mentioned in the first comment, for reference...
Further investigation suggests that the alignment may be a red herring; there's definitely something nondeterministic going on (stack alignment? cache effects?) but it's not clear to me that code alignment is the sole cause. Very heisenbuggy behavior, alas...
I've seen the same thing on some micro benchmarks when investigating fixing the stack alignment. The same core loop code emitted in slightly different memory footprint can give 20% different performance. I thought it was loop alignment as well but maybe related to placement of instructions WRT cache lines? If an instruction spans a cache line and is a branch target, does that hurt performance? Some hand written ASM tests would make sense to try.
This is a weird one; loop alignment *might* be an issue but it's definitely not the only issue; I have a case here in isolation in which two runs are nearly 3x different in speed, but the jitted code is *identical* between runs; the only difference I've found is a 32-byte difference in the stack pointer between the runs (but both are 16-byte aligned). A real head-scratcher.
FWIW, the particular case I was investigating doesn't seem to be due to loop alignment; the actual nature of what's going on is still a mystery. I'm going to withdraw this bug unless someone thinks that loop alignment is worth pursuing in its own right.
Word aligns all LIR_label locations and method entries. jsbench results on a MacPro Intel Xeon (Westmere?) untyped: min avg (n=3) Crypt 1.06762 0.979522% Euler -0.50803 -0.594995% FFT 1.1516 1.01755% HeapSort -0.340948 -0.136347% LUFact -1.16134 -0.420438% Moldyn 1.14327 1.03043% RayTracer -0.662927 -0.880461% SOR 0.123411 0.605343% Series -2.10371 -2.04172% SparseMatmult 0.230807 -0.084077% typed: Crypt -0.738916 -0.737735% Euler 0.0430108 -0.120091% FFT -0.461681 0.211397% HeapSort 0.783972 1.04439% LUFact 1.20482 1.38671% Moldyn 0.716253 0.705404% RayTracer 1.16175 1.24967% SOR 0.790068 0.993806% Series 2.92605 3.02441% SparseMatmult 1.86306 1.12137%
(In reply to comment #9) > Word aligns all LIR_label locations and method entries. > jsbench results on a MacPro Intel Xeon (Westmere?) BTW, the results show percentage improvement over baseline from 3 runs (sorry about the meaningless decimal points).
I tried this on TM, I got no change on Sunspider but a 1--2% improvement on Kraken. Hard to tell if it's just noise, but it didn't seem to hurt.
More reliable and somewhat less conclusive results on jsbench: MacPro Xeon (Westmere), multiuser (noise: 0.1-0.2% with two outliers ~0.8%), 10 iterations untyped: Euler -0.9% FFT 0.2% HeapSort -1.2% LUFact -0.6% Moldyn 1.5% RayTracer -1.6% SOR -0.3% Series -0.6% SparseMatmult - 0.7% typed: Euler -0.0% FFT -0.8% HeapSort 1.5% LUFact 1.1% Moldyn 0.0% RayTracer 0.8% SOR 0.9% Series 2.9% SparseMatmult 1.0% MacBookPro Core 2 Duo, single user (noise 0.0% - 0.1%), 10 runs untyped: Crypt -0.3% Euler -1.4% FFT 1.7% HeapSort -1.2% LUFact -1.2% Moldyn 1.8% RayTracer 1.5% SOR -0.1% Series 0.5% SparseMatmult 2.1% typed: Crypt -1.0% Euler -3.5% FFT -0.5% HeapSort 2.2% LUFact -0.2% Moldyn 0.1% RayTracer 0.8% SOR 2.2% Series 0.7% SparseMatmult 0.1% The divergence on typed/Euler.as between the platforms is peculiar, otherwise typed code seems consistently better on the Xeon, although not by much.
Nanojit is long gone.
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → DUPLICATE
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: