junbin666 commited on
Commit
a67e4bb
·
verified ·
1 Parent(s): b95d589

Launch honest RAPIDS cuDF decision lab

Browse files
Files changed (2) hide show
  1. README.md +48 -4
  2. index.html +33 -17
README.md CHANGED
@@ -1,10 +1,54 @@
1
  ---
2
- title: Cudf Game Analytics Benchmark
3
- emoji: 📉
4
  colorFrom: green
5
- colorTo: green
6
  sdk: static
 
7
  pinned: false
 
 
 
 
 
 
 
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>