Kiet Vu

Hydrogen Bomb vs. Coughing Baby: H100 vs. RTX 3060

Oct 3, 2026  

In this blog, we will benchmark my RTX 3060 Mobile against an H100 using Accel-Sim, which just dropped one of its biggest updates ever. To put it in perspective, the version before that was released 4.5 years ago, and since then they just added patches, fixes and PRs along the way.

For those who don’t know, Accel-Sim/GPGPU-Sim is one of the most used GPU simulators in all of academia, if not the most. And I had a chance to contribute to that a while ago.

paper
Architecting the Next Generation of Asynchronous, Distributed GPUs for the AI Era (arXiv)
code
github.com/accel-sim/accel-sim-framework
release notes
Accel-Sim v2.0.0
all the data
H100 vs. RTX 3060, sim vs. real RTX 3060, simulator stats (interactive, best on a laptop)

Note: This is supposed to be a fun profiling blog/experiment, not a tutorial. I’m not providing the source code or step-by-step guide on how to reproduce it here (since the setup alone is such a pain). I swear I spent around 3+ hours just to get everything running smoothly, and around 5+ hours for all the runs to finish. So yeah, this is entirely a “trust me bro” situation.

TL;DR

1. What Changed in Accel-Sim 2.0

The paper sums it up in one table [1]:

Inherited from Accel-Sim 1.xAdded in Accel-Sim 2.0
# SMs132new operand collector, spinloop support, chiplet-aware CTA scheduling, Cooperative Groups support, cluster control
L1 cache / shared memory256 KB, 4 banksTMA, CGA multicast, Distributed Shared Memory
# exec units†4 FPs, 4 DPs, 4 INTs, 4 SFUs, 4 HMMAsWGMMA, UTC*MMA, warpgroup commit/wait, 2-CTA, exec unit refactor
L2 cache50 MB, 80 banksmodulo IPOLY hash, LRC, chiplet cache policies
MMA latencyfixedvariable (depending on N)
memoryHBM bandwidth/latencyHBM3, HBM3e bandwidth/latency
interconnectmonolithic crossbarchiplet interconnect, NVLink
sync primitivesbarriermbarrier, bar.arv, bar.sync, ldgstsbar, fence, UTCBAR, WARPGROUP
tracerSASS register dependencies, control flowregister value tracing, spinloop handling, multi-GPU tracing, trace compression, trace paging, tensor descriptor support, PyTorch per-layer support
performance counters5411,072
correlationkernel-level Nsight Computecycle-level GPUVision

The H100 config in Accel-Sim 1.x vs. 2.0, from Table I of the paper. †FP: single-precision floating point, DP: double-precision floating point, INT: integer, SFU: special function unit, HMMA: Volta tensor core.

On the performance side:

There are so many more features that I cannot list all of them. That’s fair game since Hopper is a big jump compared to other generations (especially when placed against my RTX 3060 Mobile). See the paper for more details (or even better, the release notes).

And it shows. On Hopper, the paper says 1.x had a 36% cycle error on HPC workloads and 46% on CUTLASS GEMMs (it couldn’t model TMA or mbarrier at all). 2.0 gets it down to 13.5% overall against a real H100.

In short, it can now simulate the warp-specialized, asynchronous style of modern AI kernels like FlashAttention or CUTLASS Hopper GEMMs.

  1. Note that ncu uses CUPTI internally, so hardware data always comes from CUPTI. Accel-Sim just calls it out explicitly this time. ↩

2. Why 2009 Kernels?

But yeah, we’re not doing that here. We’re going to benchmark it on 2009-era kernels.

“Why?” you may ask (obviously). Well, my poor laptop from 2021 is not built for this,2 and we also don’t have access to any H100 to benchmark against (technically I can rent one for $4, but yeah, I’m not running ML SASS on my laptop).

And ML in PTX mode? That’s out of the question. I don’t have all day to run that. Also, most ML kernels like cuBLAS, cuDNN and FlashAttention ship as SASS with barely any PTX, so PTX mode often can’t even run them.

So 2009 kernels we go.

  1. It has trouble booting up, so I avoid using it at all costs (only when I seriously have to, like for simulating this battle). The fan goes full jet engine the moment I open anything (Alienware pls fix this), the battery drains super fast (maybe too old), and it always wants to update before I can shut it down. And then it won’t even finish the update. ↩

3. Setup

The two contenders, as configured in the simulator:

RTX 3060 MobileH100
SMs30132
core clock975 MHz (base, what ncu locks it to)1980 MHz (SXM max boost)
L224 sub-partitions, at the core clock80 sub-partitions × 640 KB = 50 MB, at 2× the core clock
memory channels1240
DRAM modeldetailed GDDR6simple fixed latency
launch latency5,000 cycles per kernel3,000 cycles per kernel
simulation modesSASS (trace replay) and PTXPTX only (no H100 to record traces on)

So three configs in total, all with warm L2 (cudaMemcpy data lands in L2, which is what real GPUs do, more on that in section 9): RTX3060M-MEMCPYL2ON-SASS, RTX3060M-MEMCPYL2ON-PTX and H100-PTX.

We will be using 2 test suites: Rodinia 2.0-ft [2] and ISPASS-2009 [3].

Rodinia 2.0-ft

Rodinia (U. Virginia, 2009) is a suite of small kernels from many fields. The -ft versions used here were shrunk by UBC so they finish fast in GPGPU-Sim. They exist as smoke tests, not as stress tests (see gpu-app-collection/src/cuda/rodinia/2.0-ft/README.md). Keep in mind that these are tiny inputs.

appwhat the GPU doesinputkernelsmax CTAs × threads
backprop
machine learning
Trains one layer of a 2-layer neural net. layerforward does a shared-memory reduction of input × weight, then adjust_weights applies the update4,096 input nodes2256 × 256
bfs
graph traversal
Breadth-first search, one thread per node. Kernel expands the frontier, Kernel2 swaps masks. Repeats once per BFS level (8 levels × 2 kernels)4,096-node graph168 × 512
heartwall
medical imaging
Tracks the heart wall in an ultrasound video frame. Each CTA follows one sample point, matching a template by correlation1 frame151 × 512
hotspot
physics / EDA
2-D thermal stencil over a chip floor plan. Each launch advances several time steps at once (a “pyramid” of halos in shared memory)30×30 grid, 40 steps, pyramid 6764 × 256
lud
linear algebra
Blocked LU decomposition. The diagonal, perimeter and internal kernels shrink as the factorization proceeds (9 CTAs down to 1)64×64 matrix109 × 256
nn
data mining
k-nearest-neighbor: Euclidean distance from every hurricane record to a target lat/long4 record files4938 × 16
nw
bioinformatics
Needleman–Wunsch DNA alignment. Fills a DP matrix in anti-diagonal waves: CTA count grows 1→8, then shrinks 8→1128×128, penalty 10158 × 16
pathfinder
dynamic programming
Finds the min-cost path down a 2-D grid, row by row, several rows per launch1,000 cols × 20 rows, pyramid 545 × 256
srad_v2
image processing
Speckle-reducing anisotropic diffusion (ultrasound de-noising). Two stencil kernels per iteration128×128 image, 2 iterations464 × 256
streamcluster
data mining
Online k-median clustering. pgain evaluates opening a new center and is called from a CPU loop1,024 points, dim 161302 × 512

5 of the 10 apps (bfs, lud, nw, pathfinder, streamcluster) never launch more than 9 CTAs, so they can’t even fill the 30-SM laptop GPU. streamcluster runs 130 kernels of 2 CTAs each: 2 of 30 SMs busy, every time.

ISPASS-2009

appwhat the GPU doesinputkernelsmax CTAs × threads
BFS
graph traversal
Breadth-first search (different code from Rodinia’s)65,536-node graph9256 × 256
LIB
finance
LIBOR market model Monte Carlo: prices a swaption portfolio, one path per thread. Two kernels: prices, then prices plus sensitivities. Long, compute-heavy, few CTAs4,096 paths, 15 swaptions264 × 64
LPS
physics
3-D Laplace equation solver (Jacobi iteration on a regular grid). Each thread walks down the z-axis, keeping 3 planes in shared memory100×100×100 grid, 1 iteration1100 × 128
NN
machine learning
Convolutional neural net inference (LeNet-style, 29×29 handwritten-digit images, 4 layers, one kernel per layer)28 images42,800 × 1–169
NQU
search
N-Queens solver: the CPU places the first 2 queens, then each thread backtracks the rest with a bitmask stack8 queens1256 × 96
RAY
graphics
Ray tracer, one thread per pixel256×256 image1512 × 128
STO
storage systems
StoreGPU: SHA-1 hashes of overlapping 52-byte chunks, one per thread (the sliding window used for dedup in content-addressable storage)49,152 chunks (~192 KB)1384 × 128
WP
weather
WSM5 microphysics from the WRF weather model. Big per-thread state, register-heavyWRF snapshot (step 10)172 × 64

ISPASS gives the H100 more to chew on (NN reaches 2,800 CTAs, and BFS, NQU, RAY and STO launch 256–512). But the two longest-running apps, LIB (64 CTAs) and WP (72 CTAs), still launch fewer CTAs than the H100 has SMs.

NQU’s 256 is misleading too. With 8 queens, the CPU only finds 21 ways to place the first 2 queens, so 21 threads do real work. The other 255 CTAs just add up zeros. That’s why NQU barely gains from the extra SMs (1.08×) even though it “launches” 256 CTAs.

Note: LIB, NN and WP are skipped (hours each and more than 2.4 GB of RAM each, my laptop can’t handle that safely). STO only runs on the 3060 side, since its H100 sim needs more than 3.5 GB of RAM. That leaves 14 apps in the H100 comparison.

Bar chart of the largest kernel launch per app, in CTAs, with lines at 30 and 132 SMs
CTAs in each app’s largest launch. The light bars can’t even fill the 3060. (interactive)

4. Results

Reading the specs, it may seem that an H100 would get a 4–10× speedup against a mere RTX 3060: 132 SMs vs. 30 SMs, 1.98 GHz vs. 975 MHz (actually I’m not sure about both clocks)3, and 10× the memory bandwidth.

But against my real laptop running at its real clock, the simulated H100 is only around 1.82× faster across 14 apps. On some apps it’s not faster at all, and it’s even slower on a few.

Bar chart of the simulated H100's speedup over the real laptop, at base and unlocked clocks
Simulated H100 vs. my real laptop. Below the dashed line, the laptop wins. (interactive)

“Real clock” here means unlocked. While profiling, ncu locks the laptop to its 0.97 GHz base clock. Unlocked, it runs at about 1.35 GHz, which makes it 1.31× faster (geomean). The run-to-run spread is 4% or less on every app except heartwall (11%). Against the base-locked laptop, the H100 would be 2.39×.

1.82× is the number to quote for “H100 vs. my laptop”, with one big asterisk: the H100 side is a model running in PTX mode, with no H100 to check it against (section 7).

  1. The clocks aren’t documented thoroughly, and different sites give different numbers for both GPUs. For the H100, I’m going with the Accel-Sim config: 1980 MHz. For my laptop, the numbers are derived from my own runs: ncu locks it at 975 MHz, and unlocked it averages about 1.35 GHz over these kernels. ↩

5. Speedup

Running simulator against simulator (warm L2 on both, laptop modeled at its 0.975 GHz base clock) brings the gap up to 2.74×:

geomean, 14 appsRodinia (10)ISPASS (4)
H100 wall-time speedup2.74×2.74×2.72×
… of which clock (1980 / 975 MHz)2.03×2.03×2.03×
… of which cycles (cycle×)1.35×1.35×1.34×
… kernel execution only (exec×, launch latency removed)1.21×1.16×1.34×

Which breaks down like this:

2.74× = 2.03× clock × 1.11× launch overhead × 1.21× kernel execution

clock
RTX 3060: 975 MHz, H100: 1.98 GHz. The honest clock ratio is 1.47×, since the laptop actually runs at 1.35 GHz when we unlock the Nsight Compute clock (it can go even higher, but the kernels only last microseconds). So base-locked 3060 vs. boosted H100 is kinda unfair here.
launch overhead
The config says 3,000 cycles per kernel for the H100 vs. 5,000 for the RTX 3060. It’s a fixed cost added to every kernel launch, and it comes from calibration, not microarchitecture. Keep this one in mind for finding #1.
kernel execution
This is the part that benefits from the extra SMs. Only 1.21×, and the next section explains why.
Bar chart of the share of simulated cycles spent in kernel launch latency, RTX 3060 vs. H100
Share of simulated cycles spent waiting on the fixed launch latency. (interactive)

6. SM Scaling

Comparing on SM count is kinda unfair, since the 132 SMs barely matter here: those 2009-era programs can’t really use them.

Bar chart of H100 per-cycle speedup, all cycles vs. kernel execution only, with SM headroom marked
H100 speedup per cycle (clock removed). The black ticks are the SM headroom: the most the extra SMs could give, min(CTAs, 132) / min(CTAs, 30). (interactive)

The apps that launch ≤ 30 CTAs (bfs, lud, nw, pathfinder, streamcluster) can’t even fill the 3060. Their exec× geomean is 0.89×, so the H100 runs their kernels slower per cycle. The other 9 apps get 1.44×. As for kernel execution:

Also notice how each SM in the RTX 3060 packs more CTAs than the H100? The CTA scheduler deals CTAs out one per SM per round, like dealing cards. For most apps (9 of 15 launch ≤ 132 CTAs), the H100 is done dealing in one round with plenty of SMs left empty, while the RTX 3060 needs several rounds. So CTAs end up sharing SMs (though they usually still all run at the same time). That shows up as much lower occupancy on the H100: backprop drops from 80.7% to 23.8%, nn from 61.1% to 11.0%, and BFS from 60.8% to 14.1%.

7. Can We Trust the Simulator?

None of the numbers above mean much if the simulator is way off. There’s no H100 to check against, but there is a real RTX 3060. From the correlation dashboard, 15 apps (the 14 above plus STO, which only runs on the 3060), warm L2:

statSASS (trace replay)PTX
GPC cyclescorrel 0.996, err 15.3%0.991, 27.7%
warp instructions0.9997, 0.3%0.961, 15.4%
L2 reads0.998, 2.0%0.996, 35.4%
L2 write hits0.999, 17.1% (~3% without STO)0.888, 54.1%
L1D read hits0.998, 8.4%0.907, 32.9%
L2 read hits0.72, broken (old sim issue, not new in 2.0)0.73
DRAM reads0.21, 92%0.22, 92%
Scatter plot of simulated vs. real RTX 3060 cycles for SASS and PTX modes
Simulated vs. real RTX 3060 cycles, one point per app. On the dashed line, the sim matches hardware. (interactive)

So SASS mode is good on cycles and very good on instructions and L2 traffic. For reference, the paper reports 0.99 correlation and 13.5% cycle error against a real H100, on more than 34,000 kernels of modern workloads, so 15.3% on my 3060 is in the same range. PTX mode (the only mode available for the H100) is roughly 2× less accurate on cycles, and executes ~15% different instruction counts (PTX ≠ the SASS that ptxas actually produces). It’s worst on tiny latency-bound kernels (nw +78%, lud +59%).

L2 write hits use the counter from my PR #141, which counts writes to never-read lines the way NVIDIA hardware does (the mapping that uses it isn’t merged yet, see concerns). They’re within 6% on 12 of 15 apps (NQU is off by 9% and pathfinder by 17%, on only a few hundred hits). STO alone is +213% (sim 24,576 vs. hardware 7,856): it writes one byte at a time, and real hardware seems to merge those writes somewhere between L1 and L2. I dug into that one in the PR discussion.

DRAM traffic and L2 read hits don’t line up in any mode,4 so I don’t read into those numbers anywhere in this post.

As for the H100 side: it’s a model only. No H100 hardware or traces exist here. The direction of each finding is solid (the clock dominates, and few-CTA kernels can’t use the H100), because it follows from CTA counts and config constants, not fine timing. But treat individual exec× values as ±30%.

  1. The sim over-counts L2 read hits (an old issue, not new in 2.0), and DRAM is probably a unit mismatch: requests vs. 32-byte sectors. ↩

8. Launch Latency

15.3% cycle error sounds good. But look at what happens to the SASS error when the fixed launch latency (5,000 cycles per kernel) is taken out of the simulated cycles:

applaunch share of sim cyclesSASS errorSASS error, launch latency removed
Rodinia 2.0-ft
backprop42%−26%−57%
bfs65%+22%−57%
heartwall49%+2%−48%
hotspot33%−24%−49%
lud30%+2%−29%
nn58%+20%−49%
nw58%+2%−57%
pathfinder67%+21%−61%
srad_v253%−7%−56%
streamcluster58%+31%−45%
ISPASS-2009
BFS21%−1%−22%
LPS4%−10%−14%
NQU20%−23%−38%
RAY13%+15%+0%
STO11%+23%+10%

On every Rodinia app except lud, the error swings to around −50%. In other words, the simulated kernels run about 2× faster than the real ones, and the fixed launch cost fills the gap. heartwall and nw look almost perfect (+2%), but half of their simulated cycles come from that one config number.

That doesn’t mean the number is wrong. Real kernels do pay a startup cost, and the config sets 5,000 cycles to match it. But on apps this small, a 15% error says more about how well that one constant was tuned than about how well the SMs and memory are modeled. The ISPASS apps run long enough for launch to stop mattering, and there the errors barely move (LPS −10% → −14%, RAY +15% → +0%).

It matters for the H100 too: launch is 1.11× of the 2.74× speedup, and it comes from 3,000 vs. 5,000 cycles in two config files.

9. Cold L2

-gpgpu_perf_sim_memcpy is a GPGPU-Sim knob that decides whether the simulator pushes cudaMemcpy writes through L2, so kernels start warm. On every NVIDIA GPU since Fermi, L2 is a memory-side cache that all DRAM traffic passes through, so this applies to the 3060 as much as to the H100. Every upstream config, GTX 480 through H200, uses 1.

My 3060M config had 0. 2.0 didn’t touch the memcpy code. The 0 came from our own config (after running the microbenchmarking kernels), not from upstream.

But that microbenchmark run was a false negative. I re-ran it 10 times, and in 7 runs the first load after a cudaMemcpy costs exactly an L2 hit (220.1 vs. 220.6 cycles). The “No” runs come from clock noise: it times two separate kernels at unlocked clocks, and calls anything more than 10% apart “not cached”, in either direction. So the real 3060 keeps copied data in L2. The config is now set to 1, and everything in this post uses warm L2 on both GPUs.

With the old setting, stock vs. stock would’ve handed the H100 a warm cache and the 3060 a cold one (2.94× instead of 2.74×), and the 3060 sim would’ve looked worse than it is (SASS cycle error 18.5% instead of 15.3%, PTX 35% instead of 28%).

Funny enough, the real GPU barely cares. Re-profiling with ncu flushing all caches before every kernel vs. not flushing changes real 3060 cycles by only +0.7% geomean (heartwall +9%, all others within ±3%), since these small apps warm L2 quickly by themselves anyway.

10. Simulator Speed?

We measured that 2.0 is 25% slower on our SASS runs, not 2.2× faster like the paper claimed. Same traces, byte-identical gpgpusim.config, Rodinia 2.0-ft on RTX3060M:

app1.x (July)2.0 (now)
backprop11 s13 s
hotspot24 s27 s
nn16 s27 s
streamcluster39 s47 s
all 10122 s152 s

Potential Explanation: one sample each, integer-second timers, and July’s runs may have shared the machine with other jobs. If anything, that would have slowed July, which makes 2.0’s slowdown conservative.

Not saying they’re wrong tho. The 2.2× is relative to 1.x on their workloads, and they use fast paths I don’t (simple DRAM, the new trace format). 2.0 also does a lot more bookkeeping per cycle (11,072 counters vs. 54), which plausibly costs the most on apps with many memory accesses per cycle (nn is the worst at +69%).

The absolute speed is roughly the same ballpark. The paper says “27.5k kilo warp instructions per second” (the k + kilo looks like a double unit, so I read it as ~27.5K warp instructions/s), and my SASS runs do ~35K warp instructions/s (median, 6.6K–102K across apps).

We also have to be careful with units here (speaking from experience (I was not careful)): GPGPU-Sim’s printed gpgpu_simulation_rate counts thread instructions (0.1–3.2M/s for the same runs), which is 7–32× bigger than warp instructions, depending on how many threads in each warp are active.

Each simulated H100 cycle costs 1.7–5.5× a 3060M cycle. The pathfinder smoke test: H100 10.3 s and 820 MB vs. RTX3060M 2.9 s and 174 MB. Across Rodinia (PTX, warm L2 on both):5

appmax CTAs3060M sim cycles/sH100 sim cycles/scost per cycleH100 needs fewer cycles bywall time 3060 → H100
backprop2565793361.7×2.0×42 s → 36 s
heartwall517063701.9×1.4×14 s → 19 s
hotspot641,1694452.6×2.4×95 s → 105 s
lud≤ 919,9403,6645.4×1.1×13 s → 66 s
bfs812,6242,3135.5×1.2×10 s → 46 s

Why? The simulator ticks every component every cycle, busy or not:

Apps that launch only a few CTAs leave more than 120 SMs idle, but still pay to tick them. So the penalty grows as the CTA count shrinks (backprop 1.7× → bfs 5.5×). Simulating a 132-lane highway with 8 cars costs the same as a full one.

  1. One run each, so take the exact ratios loosely. Wall time on my laptop swings a lot. Backprop’s 3060 run took 42 s here but 21–26 s in other runs. ↩

11. Other Concerns

12. Verdict

The hydrogen bomb, obviously. But only by 1.82× against my real laptop, most of that from its clock, and on lud, nw and streamcluster the coughing baby ties or wins. Without modern workloads, the H100 is just a normal GPU with more SMs and more bandwidth, and these apps can’t even use the SMs.

Honestly though, the battle wasn’t the interesting part. Running the benchmarks was easy (I’m lying). The findings above are what’s interesting. You only catch stuff like that by correlating against real hardware and asking why the numbers look the way they do. That was also the point of this whole thing.

Next up: rent a real H100 ($4/hour I believe), run the same correlation flow on it (ncu, and GPUVision this time), and trace modern kernels like CUTLASS Hopper GEMMs and FlashAttention-3 in SASS mode, where TMA, clusters and WGMMA actually show up.

It won’t be a rematch though. My poor laptop is not running heavy ML workloads, so the 3060 sits that one out.

See you in the next one!

References

  1. J. Pan et al., “Architecting the next generation of asynchronous, distributed GPUs for the AI era,” 2026, arXiv:2608.22602.
  2. S. Che et al., “Rodinia: A benchmark suite for heterogeneous computing,” in Proc. IEEE Int. Symp. Workload Characterization (IISWC), 2009, pp. 44–54, doi: 10.1109/IISWC.2009.5306797.
  3. A. Bakhoda, G. L. Yuan, W. W. L. Fung, H. Wong, and T. M. Aamodt, “Analyzing CUDA workloads using a detailed GPU simulator,” in Proc. IEEE Int. Symp. Perform. Anal. Syst. Softw. (ISPASS), 2009, pp. 163–174, doi: 10.1109/ISPASS.2009.4919648.