Launch honest RAPIDS cuDF decision lab
Browse files- README.md +48 -4
- index.html +33 -17
README.md
CHANGED
|
@@ -1,10 +1,54 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
colorFrom: green
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
|
|
|
| 7 |
pinned: false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: cuDF Game Analytics Benchmark
|
| 3 |
+
emoji: 🎮
|
| 4 |
colorFrom: green
|
| 5 |
+
colorTo: gray
|
| 6 |
sdk: static
|
| 7 |
+
app_file: index.html
|
| 8 |
pinned: false
|
| 9 |
+
license: mit
|
| 10 |
+
short_description: An honest RAPIDS cuDF benchmark and GPU-fit decision lab
|
| 11 |
+
tags:
|
| 12 |
+
- nvidia
|
| 13 |
+
- rapids
|
| 14 |
+
- cudf
|
| 15 |
+
- gpu
|
| 16 |
+
- data-science
|
| 17 |
+
- game-analytics
|
| 18 |
---
|
| 19 |
|
| 20 |
+
# cuDF Game Analytics Benchmark
|
| 21 |
+
|
| 22 |
+
An interactive portfolio companion to the reproducible Colab benchmark in
|
| 23 |
+
[`jjfishjj/cudf-game-analytics-benchmark`](https://github.com/jjfishjj/cudf-game-analytics-benchmark).
|
| 24 |
+
|
| 25 |
+
The key result is deliberately honest: a naïve pandas-to-`cudf.pandas`
|
| 26 |
+
migration did **not** accelerate every workload. At 20M synthetic game events,
|
| 27 |
+
RFM and retention were slower on a Colab T4 because unsupported or small-result
|
| 28 |
+
operations could not amortize GPU overhead. The public notebook then rewrites
|
| 29 |
+
the funnel with GPU-native groupby operations and provides a 50M-row
|
| 30 |
+
sort/groupby/merge workload for further measurement.
|
| 31 |
+
|
| 32 |
+
## Measured evidence
|
| 33 |
+
|
| 34 |
+
| 20M-row workload | pandas CPU | cudf.pandas GPU | Interpretation |
|
| 35 |
+
| --- | ---: | ---: | --- |
|
| 36 |
+
| RFM | 0.39 s | 0.65 s | GPU 1.7× slower |
|
| 37 |
+
| Retention | 0.42 s | 0.69 s | GPU 1.6× slower |
|
| 38 |
+
| Funnel using Python sets | 4.11 s | 3.63 s | Near parity |
|
| 39 |
+
|
| 40 |
+
The Space does not execute cuDF or claim unrecorded GPU-native speedups. It
|
| 41 |
+
visualizes the recorded measurements and provides a deterministic GPU-fit
|
| 42 |
+
decision lab. Run the linked notebook on a T4 to generate new hardware results.
|
| 43 |
+
|
| 44 |
+
- **Space:** <https://huggingface.co/spaces/junbin666/cudf-game-analytics-benchmark>
|
| 45 |
+
- **GitHub:** <https://github.com/jjfishjj/cudf-game-analytics-benchmark>
|
| 46 |
+
- **Colab:** <https://colab.research.google.com/github/jjfishjj/cudf-game-analytics-benchmark/blob/main/notebooks/game_analytics_benchmark.ipynb>
|
| 47 |
+
|
| 48 |
+
## Resume-ready summary
|
| 49 |
+
|
| 50 |
+
> Benchmarked pandas versus RAPIDS `cudf.pandas` on 20M synthetic game events,
|
| 51 |
+
> traced GPU losses to CPU fallback and transfer overhead, and redesigned the
|
| 52 |
+
> workload around native groupby/merge/sort paths; published an interactive
|
| 53 |
+
> decision lab that separates measured evidence from unverified projections.
|
| 54 |
+
|
index.html
CHANGED
|
@@ -1,19 +1,35 @@
|
|
| 1 |
<!doctype html>
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
<!doctype html>
|
| 2 |
+
<html lang="zh-Hant">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
| 5 |
+
<meta name="description" content="Interactive RAPIDS cuDF game analytics benchmark and GPU-fit decision lab.">
|
| 6 |
+
<title>cuDF Game Analytics Benchmark</title>
|
| 7 |
+
<style>
|
| 8 |
+
:root{--bg:#080a09;--panel:#121613;--line:#29302b;--text:#f0f3f1;--muted:#9aa39d;--green:#76b900;--lime:#b7ef55;--red:#ff7262;--cyan:#61d3c5;--amber:#f0c85c;--shadow:0 18px 60px #0007}*{box-sizing:border-box}body{margin:0;background:radial-gradient(circle at 85% 5%,#76b90022,transparent 30%),var(--bg);color:var(--text);font:15px/1.6 Inter,ui-sans-serif,system-ui,sans-serif}.shell{width:min(1160px,calc(100% - 28px));margin:auto}a{color:inherit}.nav{height:68px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line)}.brand{display:flex;align-items:center;gap:10px;font-weight:850}.logo{display:grid;place-items:center;width:35px;height:35px;border-radius:8px;background:var(--green);color:#061000}.actions{display:flex;gap:8px}.btn{padding:9px 13px;border:1px solid var(--line);border-radius:8px;color:var(--text);background:#121613;text-decoration:none;font:inherit;font-size:12px;font-weight:800;cursor:pointer}.btn:hover{border-color:#607063}.btn.primary{background:var(--green);border-color:var(--green);color:#071000}.hero{padding:60px 0 34px}.eyebrow{margin:0 0 12px;color:var(--lime);font-size:11px;font-weight:900;letter-spacing:.13em;text-transform:uppercase}.hero h1{max-width:920px;margin:0;font-size:clamp(40px,7vw,76px);line-height:1.02;letter-spacing:-.055em}.lead{max-width:760px;margin:22px 0;color:#c1c9c3;font-size:17px}.badges{display:flex;flex-wrap:wrap;gap:8px}.badge{padding:6px 10px;border:1px solid var(--line);border-radius:99px;color:var(--muted);font-size:11px}.badge.live{color:var(--lime);border-color:#76b90077;background:#76b90012}.section-head{display:flex;justify-content:space-between;align-items:end;gap:16px;margin:18px 0 12px}.section-head h2{margin:0;font-size:19px}.section-head p{margin:0;color:var(--muted);font-size:12px}.card{border:1px solid var(--line);border-radius:14px;background:#111512eF;box-shadow:var(--shadow)}.evidence{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}.metric{padding:18px}.metric small{color:var(--green);font-weight:900;letter-spacing:.08em}.metric h3{margin:7px 0 2px;font-size:18px}.times{display:flex;gap:9px;margin:15px 0}.time{flex:1;padding:10px;border:1px solid var(--line);border-radius:8px}.time span{display:block;color:var(--muted);font-size:10px}.time b{font:850 18px/1.4 ui-monospace,SFMono-Regular,monospace}.ratio{font-size:12px;font-weight:800}.ratio.loss{color:var(--red)}.ratio.neutral{color:var(--amber)}.bar{display:flex;height:7px;gap:3px;margin-top:10px}.bar i{display:block;border-radius:5px}.cpu{background:#69736d}.gpu{background:var(--green)}.lab{display:grid;grid-template-columns:.8fr 1.2fr;gap:13px;margin:26px 0}.controls,.verdict{padding:22px}.controls label{display:block;margin:13px 0 5px;color:#cfd6d1;font-size:12px;font-weight:800}.controls select{width:100%;padding:11px;border:1px solid #38423b;border-radius:8px;background:#090c0a;color:var(--text);font:inherit}.controls .btn{width:100%;margin-top:17px}.verdictbox{min-height:270px;padding:20px;border:1px solid var(--line);border-radius:10px;background:#090c0a}.scoreline{display:flex;justify-content:space-between;align-items:center;gap:20px}.scoreline b{font-size:24px}.score{display:grid;place-items:center;width:62px;height:62px;border-radius:50%;border:6px solid var(--green);font:900 17px/1 ui-monospace,SFMono-Regular,monospace}.decision{margin:17px 0;padding:12px;border-left:3px solid var(--green);background:#76b90010}.reasons{margin:0;padding-left:20px;color:#bdc6bf}.reasons li{margin:7px 0}.boundary{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:0 0 42px}.boundary .card{padding:19px}.boundary b{display:block;margin-bottom:6px}.boundary p{margin:0;color:var(--muted);font-size:12px}.measured b{color:var(--lime)}.notmeasured b{color:var(--amber)}footer{display:flex;justify-content:space-between;gap:20px;padding:24px 0 36px;border-top:1px solid var(--line);color:var(--muted);font-size:11px}@media(max-width:800px){.evidence,.lab,.boundary{grid-template-columns:1fr}.hero{padding-top:38px}.metric{padding:16px}.nav .hide{display:none}}@media(max-width:480px){.hero h1{font-size:40px}.shell{width:min(100% - 18px,1160px)}footer{flex-direction:column}}
|
| 9 |
+
</style>
|
| 10 |
+
</head>
|
| 11 |
+
<body>
|
| 12 |
+
<nav class="shell nav"><div class="brand"><span class="logo">R</span><span>RAPIDS Decision Lab</span></div><div class="actions"><a class="btn hide" href="https://github.com/jjfishjj/cudf-game-analytics-benchmark" target="_blank" rel="noopener">GitHub ↗</a><a class="btn primary" href="https://colab.research.google.com/github/jjfishjj/cudf-game-analytics-benchmark/blob/main/notebooks/game_analytics_benchmark.ipynb" target="_blank" rel="noopener">Run on T4 ↗</a></div></nav>
|
| 13 |
+
<main class="shell">
|
| 14 |
+
<section class="hero"><p class="eyebrow">NVIDIA RAPIDS · honest benchmark</p><h1>When is GPU actually faster?</h1><p class="lead">2,000 萬筆遊戲事件實測:GPU 並非自動勝出。價值不在喊「快幾倍」,而在辨識 CPU fallback、資料搬移與可原生向量化的運算邊界。</p><div class="badges"><span class="badge live">● Public evidence</span><span class="badge">Colab T4</span><span class="badge">20M rows</span><span class="badge">RFM · retention · funnel</span></div></section>
|
| 15 |
+
<div class="section-head"><div><p class="eyebrow">Recorded run</p><h2>同機 CPU vs T4 GPU</h2></div><p>越短越快 · notebook 實測值</p></div>
|
| 16 |
+
<section class="evidence">
|
| 17 |
+
<article class="card metric"><small>01 · RFM</small><h3>Fallback-heavy segmentation</h3><div class="times"><div class="time"><span>pandas CPU</span><b>0.39s</b></div><div class="time"><span>cuDF GPU</span><b>0.65s</b></div></div><div class="ratio loss">GPU 1.7× slower</div><div class="bar"><i class="cpu" style="width:38%"></i><i class="gpu" style="width:62%"></i></div></article>
|
| 18 |
+
<article class="card metric"><small>02 · RETENTION</small><h3>Small grouped output</h3><div class="times"><div class="time"><span>pandas CPU</span><b>0.42s</b></div><div class="time"><span>cuDF GPU</span><b>0.69s</b></div></div><div class="ratio loss">GPU 1.6× slower</div><div class="bar"><i class="cpu" style="width:38%"></i><i class="gpu" style="width:62%"></i></div></article>
|
| 19 |
+
<article class="card metric"><small>03 · FUNNEL</small><h3>Python set intersection</h3><div class="times"><div class="time"><span>pandas CPU</span><b>4.11s</b></div><div class="time"><span>cuDF GPU</span><b>3.63s</b></div></div><div class="ratio neutral">≈ parity · 1.13×</div><div class="bar"><i class="cpu" style="width:53%"></i><i class="gpu" style="width:47%"></i></div></article>
|
| 20 |
+
</section>
|
| 21 |
+
<section class="lab">
|
| 22 |
+
<article class="card controls"><p class="eyebrow">Interactive rubric</p><h2>GPU-fit analyzer</h2><label for="rows">資料規模</label><select id="rows"><option value="5">5M rows</option><option value="20" selected>20M rows</option><option value="50">50M rows</option></select><label for="operation">商業分析</label><select id="operation"><option value="rfm">RFM segmentation</option><option value="retention">Retention cohorts</option><option value="funnel">Payment funnel</option><option value="sort">Large sort / multi-agg / join</option></select><label for="path">實作路徑</label><select id="path"><option value="fallback">pandas idioms / Python objects</option><option value="native">Native groupby / merge / sort</option></select><button class="btn primary" id="analyze">分析 GPU 適配度</button></article>
|
| 23 |
+
<article class="card verdict"><p class="eyebrow">Decision output</p><div class="verdictbox"><div class="scoreline"><div><small id="label">LOW GPU FIT</small><br><b id="headline">先留在 CPU</b></div><span class="score" id="score">25</span></div><div class="decision" id="decision">20M RFM 搭配 pandas fallback-heavy 寫法,實測 GPU 反而較慢。</div><ul class="reasons" id="reasons"><li><code>qcut</code>/<code>rank</code>/<code>np.select</code> 可能離開原生 GPU 路徑。</li><li>搬移與 kernel launch 成本無法被這段工作負載攤平。</li><li>先改寫為原生 groupby/merge,再於同機重測。</li></ul></div></article>
|
| 24 |
+
</section>
|
| 25 |
+
<section class="boundary"><article class="card measured"><b>Measured evidence</b><p>上方三組時間來自公開 notebook 的 Colab 同機 CPU/T4 run,可追溯、可重跑。</p></article><article class="card notmeasured"><b>Not claimed yet</b><p>50M native sort/groupby/merge 尚未發布完整成對數字;分析器只給工程判斷,不虛構 speedup。</p></article></section>
|
| 26 |
+
</main>
|
| 27 |
+
<footer class="shell"><span>Jerome Kuo · game data PM × NVIDIA RAPIDS</span><span>Static decision lab · GPU execution runs in Colab</span></footer>
|
| 28 |
+
<script>
|
| 29 |
+
const rows=document.querySelector('#rows'),op=document.querySelector('#operation'),path=document.querySelector('#path');
|
| 30 |
+
const configs={rfm:{fallback:['qcut/rank/np.select 可能離開原生 GPU 路徑','高基數分群仍需檢查每個 operator 的支援狀態'],native:['改用原生 groupby 與向量化分箱可降低 fallback','同機重測後才能聲稱加速']},retention:{fallback:['輸出只有約 90 個 cohort,計算量偏小','kernel launch 與資料搬移容易主導總時間'],native:['nunique 可走 GPU,但小輸出仍可能吃不回啟動成本','適合與更大事件表或更多 cohort 維度一起測']},funnel:{fallback:['Python set 把 unique 結果帶回 host','CPU/GPU 交界會抵消平行運算優勢'],native:['groupby-max 布林指示欄可留在 GPU','避免 Python 物件與 host round-trip']},sort:{fallback:['大型 sort/join 若混入 Python 物件會破壞 GPU 路徑','先清除 object dtype 與逐列函式'],native:['sort/merge/multi-agg 是 GPU 適合的平行工作負載','50M rows 較可能攤平啟動與傳輸成本']}};
|
| 31 |
+
function analyze(){const n=+rows.value,o=op.value,p=path.value;let score=20;if(p==='native')score+=35;if(n>=20)score+=15;if(n>=50)score+=15;if(o==='sort')score+=15;if(o==='retention')score-=10;score=Math.max(5,Math.min(95,score));let level=score>=70?'HIGH':score>=45?'MEDIUM':'LOW';let title=score>=70?'值得進入 GPU benchmark':score>=45?'先做同機 A/B 測試':'先留在 CPU';let decision=`${n}M rows · ${op.value} · ${p==='native'?'GPU-native':'fallback-heavy'} path:${title}。`;document.querySelector('#score').textContent=score;document.querySelector('#label').textContent=`${level} GPU FIT`;document.querySelector('#headline').textContent=title;document.querySelector('#decision').textContent=decision;document.querySelector('#reasons').innerHTML=configs[o][p].map(x=>`<li>${x}</li>`).join('');}
|
| 32 |
+
document.querySelector('#analyze').addEventListener('click',analyze);[rows,op,path].forEach(x=>x.addEventListener('change',analyze));
|
| 33 |
+
</script>
|
| 34 |
+
</body>
|
| 35 |
</html>
|