firqaaa commited on
Commit
73e92a4
·
verified ·
1 Parent(s): 5852fd6

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +727 -402
index.html CHANGED
@@ -1,13 +1,12 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
-
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Interactive 3D GPU Threading</title>
8
  <style>
9
  body {
10
- font-family: 'Consolas', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
11
  background: #ffffff;
12
  color: #000000;
13
  margin: 0;
@@ -15,7 +14,7 @@
15
  line-height: 1.6;
16
  user-select: none;
17
  }
18
-
19
  .container {
20
  max-width: 1400px;
21
  margin: 0 auto;
@@ -23,7 +22,7 @@
23
  border: 2px solid #000000;
24
  padding: 30px;
25
  }
26
-
27
  h1 {
28
  text-align: center;
29
  margin-bottom: 40px;
@@ -33,7 +32,7 @@
33
  border-bottom: 2px solid #000000;
34
  padding-bottom: 15px;
35
  }
36
-
37
  .controls {
38
  display: flex;
39
  gap: 30px;
@@ -42,13 +41,13 @@
42
  justify-content: center;
43
  align-items: center;
44
  }
45
-
46
  .control-group {
47
  background: #ffffff;
48
  padding: 15px 20px;
49
  border: 1px solid #000000;
50
  }
51
-
52
  .control-group label {
53
  display: block;
54
  margin-bottom: 10px;
@@ -57,13 +56,13 @@
57
  text-align: center;
58
  font-size: 14px;
59
  }
60
-
61
  .dimension-inputs {
62
  display: flex;
63
  gap: 10px;
64
  align-items: center;
65
  }
66
-
67
  .dimension-inputs input {
68
  width: 50px;
69
  padding: 8px;
@@ -72,15 +71,15 @@
72
  color: #000000;
73
  font-weight: bold;
74
  text-align: center;
75
- font-family: inherit;
76
  }
77
-
78
  .dimension-inputs .label {
79
  font-size: 14px;
80
  color: #000000;
81
  margin: 0 5px;
82
  }
83
-
84
  .stats {
85
  display: flex;
86
  gap: 20px;
@@ -88,7 +87,7 @@
88
  flex-wrap: wrap;
89
  justify-content: center;
90
  }
91
-
92
  .stat-box {
93
  background: #ffffff;
94
  padding: 15px 20px;
@@ -96,7 +95,7 @@
96
  text-align: center;
97
  min-width: 120px;
98
  }
99
-
100
  .stat-box .label {
101
  font-size: 12px;
102
  margin-bottom: 8px;
@@ -104,24 +103,24 @@
104
  text-transform: uppercase;
105
  letter-spacing: 1px;
106
  }
107
-
108
  .stat-box .value {
109
  font-size: 24px;
110
  font-weight: bold;
111
  color: #000000;
112
  }
113
-
114
  .main-visualization {
115
  display: flex;
116
  gap: 40px;
117
  margin-bottom: 40px;
118
  }
119
-
120
  .cube-section {
121
  flex: 1;
122
  min-width: 600px;
123
  }
124
-
125
  .section-title {
126
  text-align: center;
127
  margin-bottom: 20px;
@@ -131,7 +130,7 @@
131
  border-bottom: 1px solid #000000;
132
  padding-bottom: 10px;
133
  }
134
-
135
  .cube-container {
136
  height: 500px;
137
  perspective: 1200px;
@@ -144,17 +143,17 @@
144
  cursor: grab;
145
  overflow: hidden;
146
  }
147
-
148
  .cube-container:active {
149
  cursor: grabbing;
150
  }
151
-
152
  .cube-3d {
153
  position: relative;
154
  transform-style: preserve-3d;
155
  transition: transform 0.1s ease-out;
156
  }
157
-
158
  .block-cube {
159
  position: absolute;
160
  width: 70px;
@@ -171,7 +170,7 @@
171
  text-align: center;
172
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
173
  }
174
-
175
  .block-cube:hover {
176
  background: #f0f0f0;
177
  border-width: 3px;
@@ -179,7 +178,7 @@
179
  z-index: 10;
180
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
181
  }
182
-
183
  .block-cube.selected {
184
  background: #000000;
185
  color: #ffffff;
@@ -187,7 +186,7 @@
187
  z-index: 5;
188
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
189
  }
190
-
191
  .block-label {
192
  font-size: 11px;
193
  line-height: 1.2;
@@ -196,24 +195,24 @@
196
  color: #000000;
197
  text-shadow: 0 0 2px rgba(255, 255, 255, 0.8);
198
  }
199
-
200
  .block-cube.selected .block-label {
201
  color: #ffffff;
202
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
203
  }
204
-
205
  .thread-count {
206
  font-size: 9px;
207
  color: #333333;
208
  font-weight: bold;
209
  text-shadow: 0 0 2px rgba(255, 255, 255, 0.8);
210
  }
211
-
212
  .block-cube.selected .thread-count {
213
  color: #cccccc;
214
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
215
  }
216
-
217
  .info-panel {
218
  flex: 0 0 350px;
219
  background: #ffffff;
@@ -222,7 +221,7 @@
222
  max-height: 600px;
223
  overflow-y: auto;
224
  }
225
-
226
  .info-title {
227
  font-size: 18px;
228
  font-weight: bold;
@@ -232,14 +231,14 @@
232
  border-bottom: 1px solid #000000;
233
  padding-bottom: 10px;
234
  }
235
-
236
  .info-item {
237
  margin-bottom: 20px;
238
  padding: 15px;
239
  background: #f8f8f8;
240
  border-left: 4px solid #000000;
241
  }
242
-
243
  .info-item .label {
244
  font-size: 12px;
245
  margin-bottom: 8px;
@@ -247,47 +246,48 @@
247
  text-transform: uppercase;
248
  letter-spacing: 1px;
249
  }
250
-
251
  .info-item .value {
252
  font-size: 16px;
253
  font-weight: bold;
254
  color: #000000;
255
  }
256
-
257
  .thread-detail-grid {
258
  display: grid;
259
- grid-template-columns: repeat(auto-fit, minmax(20px, 1fr));
260
- gap: 2px;
261
  margin-top: 15px;
262
- padding: 8px;
263
  background: #f0f0f0;
264
  border: 1px solid #cccccc;
265
  }
266
-
267
  .thread-detail {
268
- width: 30px;
269
- height: 30px;
270
  background: #ffffff;
271
  border: 1px solid #000000;
272
  display: flex;
273
  align-items: center;
274
  justify-content: center;
275
- font-size: 10px;
 
276
  cursor: pointer;
277
  transition: all 0.2s ease;
278
  }
279
-
280
  .thread-detail:hover {
281
  background: #000000;
282
  color: #ffffff;
283
  transform: scale(1.2);
284
  }
285
-
286
  .thread-detail.selected {
287
  background: #000000;
288
  color: #ffffff;
289
  }
290
-
291
  .instructions {
292
  text-align: center;
293
  margin-top: 20px;
@@ -297,7 +297,7 @@
297
  padding: 15px;
298
  background: #f8f8f8;
299
  }
300
-
301
  .interaction-guide {
302
  display: flex;
303
  justify-content: space-around;
@@ -307,50 +307,355 @@
307
  border: 1px solid #cccccc;
308
  font-size: 12px;
309
  }
310
-
311
  .interaction-item {
312
  text-align: center;
313
  color: #333333;
314
  }
315
-
316
  .interaction-item .icon {
317
  font-size: 18px;
318
  margin-bottom: 5px;
319
  display: block;
320
  }
321
-
322
  .spatial-explanation {
323
  background: #f8f8f8;
324
  padding: 25px;
325
  border: 2px solid #000000;
326
  margin-bottom: 30px;
327
  }
328
-
329
  .spatial-explanation h3 {
330
  color: #000000;
331
  margin-bottom: 20px;
332
  border-bottom: 1px solid #000000;
333
  padding-bottom: 10px;
334
  }
335
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  .code-example {
337
  background: #f0f0f0;
338
  padding: 20px;
339
  border: 1px solid #cccccc;
340
- font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
341
  font-size: 13px;
342
  line-height: 1.6;
343
  border-left: 4px solid #000000;
344
  margin: 15px 0;
345
  color: #000000;
346
  }
347
-
348
  .highlight {
349
  background: #e0e0e0;
350
  padding: 2px 4px;
351
  border: 1px solid #000000;
352
  }
353
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  .current-view {
355
  position: absolute;
356
  top: 10px;
@@ -363,11 +668,10 @@
363
  }
364
  </style>
365
  </head>
366
-
367
  <body>
368
  <div class="container">
369
  <h1>Interactive 3D GPU Threading</h1>
370
-
371
  <div class="controls">
372
  <div class="control-group">
373
  <label>Grid Dimensions (X × Y × Z)</label>
@@ -390,7 +694,7 @@
390
  </div>
391
  </div>
392
  </div>
393
-
394
  <div class="stats">
395
  <div class="stat-box">
396
  <div class="label">Total Blocks</div>
@@ -409,7 +713,7 @@
409
  <div class="value" id="spatialDims">3×2×2</div>
410
  </div>
411
  </div>
412
-
413
  <div class="interaction-guide">
414
  <div class="interaction-item">
415
  <span class="icon">🖱️</span>
@@ -428,238 +732,237 @@
428
  <div>Double-Click to Reset View</div>
429
  </div>
430
  </div>
431
-
432
  <div class="main-visualization">
433
  <div class="cube-section">
434
  <div class="section-title">Interactive 3D Block Grid</div>
435
-
436
  <div class="cube-container" id="cubeContainer">
437
  <div class="cube-3d" id="cube3d"></div>
438
  <div class="current-view" id="currentView">
439
  Rotation: X=15° Y=25° | Zoom: 1.0x
440
  </div>
441
  </div>
442
-
443
  <div class="instructions">
444
- Drag to rotate the cube and explore 3D spatial relationships • Scroll to zoom in/out • Click blocks
445
- to examine their threads • Double-click to reset view
446
  </div>
447
  </div>
448
-
449
  <div class="info-panel">
450
  <div class="info-title">Block & Thread Details</div>
451
  <div id="blockInfo">
452
- <div
453
- style="text-align: center; color: #666666; padding: 25px; border: 1px solid #cccccc; background: #f8f8f8;">
454
- Rotate the cube to explore spatial relationships, then click on any block to see its thread
455
- organization and understand how neighboring blocks relate to each other in 3D space.
456
  </div>
457
  </div>
458
  </div>
459
  </div>
460
-
461
  <div class="spatial-explanation">
462
  <h3>Understanding Spatial Relationships Through Direct Manipulation</h3>
463
- <p>The ability to directly manipulate the 3D cube with your cursor creates a much deeper understanding of
464
- spatial relationships than static views or sliders ever could. As you rotate the cube, you can see
465
- exactly which blocks are neighbors and how the grid extends in all three dimensions simultaneously.</p>
466
-
467
  <p><strong>Why Direct Interaction Builds Better Mental Models:</strong></p>
468
- <p>When you drag to rotate the cube, your brain naturally builds a spatial mental model that connects the
469
- visual structure to the mathematical relationships. You can see how a block at position [1,0,1] relates
470
- spatially to blocks at [0,0,1], [2,0,1], [1,1,1], and [1,0,0]. This spatial understanding is crucial for
471
- writing efficient GPU code that takes advantage of memory locality and thread cooperation patterns.</p>
472
-
473
- <p><strong>Learning Exercise:</strong> Try rotating the cube to view it from different angles while thinking
474
- about how data flows through your algorithm. Can you identify which blocks would naturally work together
475
- on shared data? The spatial arrangement you see directly represents the memory access patterns that will
476
- determine your algorithm's performance.</p>
477
-
478
  <div class="code-example">
479
- // Example: 3D convolution filter processing
480
- fn apply_3d_convolution(input: UnsafePointer[Float32], output: UnsafePointer[Float32],
481
- width: Int, height: Int, depth: Int):
482
- // Each thread processes one output voxel
483
- let <span class="highlight">x = global_idx.x</span> // Width position
484
- let <span class="highlight">y = global_idx.y</span> // Height position
485
- let <span class="highlight">z = global_idx.z</span> // Depth position
486
-
487
- if x < width and y < height and z < depth: var sum: Float32=0 // Access neighboring voxels for
488
- convolution for dz in range(-1, 2): for dy in range(-1, 2): for dx in range(-1, 2): let nx=x + dx
489
- let ny=y + dy let nz=z + dz if nx>= 0 and nx < width and ny>= 0 and ny < height and nz>= 0 and nz <
490
- depth: let neighbor_idx=nz * width * height + ny * width + nx sum +=input[neighbor_idx]
491
- * filter_weights[dz+1][dy+1][dx+1] let output_idx=z * width * height + y * width + x
492
- output[output_idx]=sum </div>
493
-
494
- <p>In this convolution example, threads processing nearby voxels (which you can see as
495
- spatially close when you rotate the cube) will access overlapping sets of input
496
- data. The 3D spatial organization ensures that these threads are grouped into nearby
497
- blocks, enabling efficient sharing of cached memory containing the input voxels they
498
- all need to access.</p>
 
 
 
 
 
499
  </div>
 
 
500
  </div>
501
-
502
- <script>
503
- let selectedBlock = null;
504
- let selectedThread = null;
505
- let isMouseDown = false;
506
- let lastMouseX = 0;
507
- let lastMouseY = 0;
508
- let rotationX = 15;
509
- let rotationY = 25;
510
- let zoom = 1.0;
511
-
512
- function updateVisualization() {
513
- const gridX = parseInt(document.getElementById('gridX').value);
514
- const gridY = parseInt(document.getElementById('gridY').value);
515
- const gridZ = parseInt(document.getElementById('gridZ').value);
516
- const blockX = parseInt(document.getElementById('blockX').value);
517
- const blockY = parseInt(document.getElementById('blockY').value);
518
- const blockZ = parseInt(document.getElementById('blockZ').value);
519
-
520
- const totalBlocks = gridX * gridY * gridZ;
521
- const threadsPerBlock = blockX * blockY * blockZ;
522
- const totalThreads = totalBlocks * threadsPerBlock;
523
-
524
- // Update stats
525
- document.getElementById('totalBlocks').textContent = totalBlocks;
526
- document.getElementById('threadsPerBlock').textContent = threadsPerBlock;
527
- document.getElementById('totalThreads').textContent = totalThreads;
528
- document.getElementById('spatialDims').textContent = `${gridX}×${gridY}×${gridZ}`;
529
-
530
- create3DCube();
531
- selectedBlock = null;
532
- selectedThread = null;
533
- updateBlockInfo();
534
- }
535
-
536
- function create3DCube() {
537
- const gridX = parseInt(document.getElementById('gridX').value);
538
- const gridY = parseInt(document.getElementById('gridY').value);
539
- const gridZ = parseInt(document.getElementById('gridZ').value);
540
- const blockX = parseInt(document.getElementById('blockX').value);
541
- const blockY = parseInt(document.getElementById('blockY').value);
542
- const blockZ = parseInt(document.getElementById('blockZ').value);
543
-
544
- const cube3d = document.getElementById('cube3d');
545
- cube3d.innerHTML = '';
546
-
547
- const spacing = 80; // Space between blocks
548
-
549
- // Create all blocks in 3D space
550
- for (let z = 0; z < gridZ; z++) {
551
- for (let y = 0; y < gridY; y++) {
552
- for (let x = 0; x < gridX; x++) {
553
- const block = createBlock3D(x, y, z, blockX, blockY, blockZ, spacing);
554
- cube3d.appendChild(block);
555
- }
556
  }
557
  }
558
-
559
- updateCubeTransform();
560
- }
561
-
562
- function createBlock3D(blockX_idx, blockY_idx, blockZ_idx, blockDimX, blockDimY, blockDimZ, spacing) {
563
- const block = document.createElement('div');
564
- block.className = 'block-cube';
565
-
566
- // Calculate center offset for better visual balance
567
- const gridX = parseInt(document.getElementById('gridX').value);
568
- const gridY = parseInt(document.getElementById('gridY').value);
569
- const gridZ = parseInt(document.getElementById('gridZ').value);
570
-
571
- const centerOffsetX = (gridX - 1) * spacing / 2;
572
- const centerOffsetY = (gridY - 1) * spacing / 2;
573
- const centerOffsetZ = (gridZ - 1) * spacing / 2;
574
-
575
- // Position in 3D space
576
- const translateX = blockX_idx * spacing - centerOffsetX;
577
- const translateY = blockY_idx * spacing - centerOffsetY;
578
- const translateZ = blockZ_idx * spacing - centerOffsetZ;
579
-
580
- block.style.transform = `translate3d(${translateX}px, ${translateY}px, ${translateZ}px)`;
581
-
582
- // Block content
583
- const label = document.createElement('div');
584
- label.className = 'block-label';
585
- label.textContent = `[${blockX_idx},${blockY_idx},${blockZ_idx}]`;
586
- block.appendChild(label);
587
-
588
- const threadCount = document.createElement('div');
589
- threadCount.className = 'thread-count';
590
- threadCount.textContent = `${blockDimX}×${blockDimY}×${blockDimZ}`;
591
- block.appendChild(threadCount);
592
-
593
- // Click handler
594
- block.addEventListener('click', (e) => {
595
- e.stopPropagation();
596
-
597
- // Remove previous selection
598
- document.querySelectorAll('.block-cube.selected').forEach(b => b.classList.remove('selected'));
599
-
600
- // Select this block
601
- block.classList.add('selected');
602
- selectedBlock = {
603
- idx: { x: blockX_idx, y: blockY_idx, z: blockZ_idx },
604
- dim: { x: blockDimX, y: blockDimY, z: blockDimZ }
605
- };
606
-
607
- updateBlockInfo();
608
- });
609
-
610
- return block;
611
  }
612
-
613
- function updateCubeTransform() {
614
- const cube3d = document.getElementById('cube3d');
615
- cube3d.style.transform = `scale(${zoom}) rotateX(${rotationX}deg) rotateY(${rotationY}deg)`;
616
-
617
- // Update current view display
618
- document.getElementById('currentView').textContent =
619
- `Rotation: X=${rotationX}° Y=${rotationY}° | Zoom: ${zoom.toFixed(1)}x`;
620
- }
621
-
622
- function updateBlockInfo() {
623
- const blockInfo = document.getElementById('blockInfo');
624
-
625
- if (!selectedBlock) {
626
- blockInfo.innerHTML = `
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
627
  <div style="text-align: center; color: #666666; padding: 25px; border: 1px solid #cccccc; background: #f8f8f8;">
628
  Rotate the cube to explore spatial relationships, then click on any block to see its thread organization and understand how neighboring blocks relate to each other in 3D space.
629
  </div>
630
  `;
631
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
632
  }
633
-
634
- const b = selectedBlock;
635
- const threadsPerBlock = b.dim.x * b.dim.y * b.dim.z;
636
-
637
- // Calculate spatial neighbors
638
- const gridX = parseInt(document.getElementById('gridX').value);
639
- const gridY = parseInt(document.getElementById('gridY').value);
640
- const gridZ = parseInt(document.getElementById('gridZ').value);
641
-
642
- const neighbors = [];
643
- const directions = [
644
- { dx: -1, dy: 0, dz: 0, name: 'left' },
645
- { dx: 1, dy: 0, dz: 0, name: 'right' },
646
- { dx: 0, dy: -1, dz: 0, name: 'back' },
647
- { dx: 0, dy: 1, dz: 0, name: 'front' },
648
- { dx: 0, dy: 0, dz: -1, name: 'below' },
649
- { dx: 0, dy: 0, dz: 1, name: 'above' }
650
- ];
651
-
652
- directions.forEach(dir => {
653
- const nx = b.idx.x + dir.dx;
654
- const ny = b.idx.y + dir.dy;
655
- const nz = b.idx.z + dir.dz;
656
-
657
- if (nx >= 0 && nx < gridX && ny >= 0 && ny < gridY && nz >= 0 && nz < gridZ) {
658
- neighbors.push(`[${nx}, ${ny}, ${nz}] (${dir.name})`);
659
- }
660
- });
661
-
662
- blockInfo.innerHTML = `
663
  <div class="info-item">
664
  <div class="label">Selected Block</div>
665
  <div class="value">Block [${b.idx.x}, ${b.idx.y}, ${b.idx.z}]</div>
@@ -671,8 +974,14 @@
671
  </div>
672
 
673
  <div class="info-item">
674
- <div class="label">Spatial Position</div>
675
- <div class="value">3D Coordinates in Grid Space</div>
 
 
 
 
 
 
676
  </div>
677
 
678
  <div style="margin-top: 20px;">
@@ -690,77 +999,93 @@
690
 
691
  <div style="margin-top: 15px; padding: 15px; background: #e8e8e8; border: 1px solid #cccccc;">
692
  <div style="font-size: 11px; color: #333333;">
693
- 💡 <strong>Learning Tip:</strong> Rotate the cube to visually identify these neighbor relationships. Blocks that appear close when you rotate are the ones that would benefit from coordinated memory access patterns in your algorithms.
694
  </div>
695
  </div>
696
  `;
697
-
698
- createThreadGrid();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
699
  }
700
-
701
- function createThreadGrid() {
702
- if (!selectedBlock) return;
703
-
704
- const threadGrid = document.getElementById('threadGrid');
705
- if (!threadGrid) return;
706
-
707
- threadGrid.innerHTML = '';
708
-
709
- const b = selectedBlock;
710
- const maxThreadsToShow = 64; // Limit for visual clarity
711
- const totalThreads = b.dim.x * b.dim.y * b.dim.z;
712
-
713
- if (totalThreads > maxThreadsToShow) {
714
- threadGrid.innerHTML = `
 
715
  <div style="text-align: center; padding: 20px; color: #666666;">
716
  Too many threads to display (${totalThreads} total)<br>
717
  Try smaller block dimensions to see individual threads
718
  </div>
719
  `;
720
- return;
721
- }
722
-
723
- threadGrid.style.gridTemplateColumns = `repeat(${Math.min(b.dim.x, 8)}, 1fr)`;
724
-
725
- // Create threads for visualization
726
- for (let z = 0; z < Math.min(b.dim.z, 4); z++) { // Show max 4 Z layers
727
- for (let y = 0; y < b.dim.y; y++) {
728
- for (let x = 0; x < b.dim.x; x++) {
729
- const thread = document.createElement('div');
730
- thread.className = 'thread-detail';
731
- thread.textContent = `${x},${y},${z}`;
732
- thread.title = `Thread [${x}, ${y}, ${z}] in Block [${b.idx.x}, ${b.idx.y}, ${b.idx.z}]`;
733
-
734
- // Calculate global position
735
- const globalX = b.dim.x * b.idx.x + x;
736
- const globalY = b.dim.y * b.idx.y + y;
737
- const globalZ = b.dim.z * b.idx.z + z;
738
-
739
- thread.addEventListener('click', () => {
740
- document.querySelectorAll('.thread-detail.selected').forEach(t => t.classList.remove('selected'));
741
- thread.classList.add('selected');
742
-
743
- selectedThread = {
744
- blockIdx: b.idx,
745
- threadIdx: { x, y, z },
746
- globalIdx: { x: globalX, y: globalY, z: globalZ },
747
- blockDim: b.dim
748
- };
749
-
750
- showThreadDetails();
751
- });
752
-
753
- threadGrid.appendChild(thread);
754
- }
755
  }
756
  }
757
  }
758
-
759
- function showThreadDetails() {
760
- if (!selectedThread) return;
761
-
762
- const t = selectedThread;
763
- const details = `
 
764
  <div style="margin-top: 20px; padding: 15px; background: #e8e8e8; border: 1px solid #000000;">
765
  <div style="font-size: 12px; font-weight: bold; margin-bottom: 10px;">Selected Thread Details:</div>
766
  <div style="font-size: 11px; line-height: 1.6;">
@@ -774,90 +1099,90 @@
774
  </div>
775
  </div>
776
  `;
777
-
778
- const blockInfo = document.getElementById('blockInfo');
779
- // Remove existing thread details
780
- const existing = blockInfo.querySelector('.thread-details');
781
- if (existing) existing.remove();
782
-
783
- const detailsDiv = document.createElement('div');
784
- detailsDiv.className = 'thread-details';
785
- detailsDiv.innerHTML = details;
786
- blockInfo.appendChild(detailsDiv);
787
- }
788
-
789
- // Mouse interaction setup
790
- function setupMouseInteraction() {
791
- const cubeContainer = document.getElementById('cubeContainer');
792
-
793
- // Mouse down event
794
- cubeContainer.addEventListener('mousedown', (e) => {
795
- isMouseDown = true;
796
- lastMouseX = e.clientX;
797
- lastMouseY = e.clientY;
798
- cubeContainer.style.cursor = 'grabbing';
799
- });
800
-
801
- // Mouse move event
802
- document.addEventListener('mousemove', (e) => {
803
- if (!isMouseDown) return;
804
-
805
- const deltaX = e.clientX - lastMouseX;
806
- const deltaY = e.clientY - lastMouseY;
807
-
808
- // Update rotation based on mouse movement
809
- rotationY += deltaX * 0.5; // Horizontal movement controls Y rotation
810
- rotationX -= deltaY * 0.5; // Vertical movement controls X rotation (inverted for natural feel)
811
-
812
- // Constrain rotations to reasonable ranges
813
- rotationX = Math.max(-90, Math.min(90, rotationX));
814
-
815
- updateCubeTransform();
816
-
817
- lastMouseX = e.clientX;
818
- lastMouseY = e.clientY;
819
- });
820
-
821
- // Mouse up event
822
- document.addEventListener('mouseup', () => {
823
- isMouseDown = false;
824
- cubeContainer.style.cursor = 'grab';
825
- });
826
-
827
- // Mouse wheel event for zooming
828
- cubeContainer.addEventListener('wheel', (e) => {
829
- e.preventDefault();
830
-
831
- const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
832
- zoom *= zoomFactor;
833
- zoom = Math.max(0.3, Math.min(3.0, zoom)); // Constrain zoom range
834
-
835
- updateCubeTransform();
836
- });
837
-
838
- // Double-click to reset view
839
- cubeContainer.addEventListener('dblclick', () => {
840
- rotationX = 15;
841
- rotationY = 25;
842
- zoom = 1.0;
843
- updateCubeTransform();
844
- });
845
-
846
- // Prevent context menu on right-click
847
- cubeContainer.addEventListener('contextmenu', (e) => {
848
- e.preventDefault();
849
- });
850
- }
851
-
852
- // Event listeners for dimension controls
853
- ['gridX', 'gridY', 'gridZ', 'blockX', 'blockY', 'blockZ'].forEach(id => {
854
- document.getElementById(id).addEventListener('input', updateVisualization);
855
  });
856
-
857
- // Initialize everything
858
- setupMouseInteraction();
859
- updateVisualization();
860
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
861
  </body>
862
-
863
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Interactive 3D GPU Threading Cube</title>
7
  <style>
8
  body {
9
+ font-family: 'Consolas', 'Courier New', monospace;
10
  background: #ffffff;
11
  color: #000000;
12
  margin: 0;
 
14
  line-height: 1.6;
15
  user-select: none;
16
  }
17
+
18
  .container {
19
  max-width: 1400px;
20
  margin: 0 auto;
 
22
  border: 2px solid #000000;
23
  padding: 30px;
24
  }
25
+
26
  h1 {
27
  text-align: center;
28
  margin-bottom: 40px;
 
32
  border-bottom: 2px solid #000000;
33
  padding-bottom: 15px;
34
  }
35
+
36
  .controls {
37
  display: flex;
38
  gap: 30px;
 
41
  justify-content: center;
42
  align-items: center;
43
  }
44
+
45
  .control-group {
46
  background: #ffffff;
47
  padding: 15px 20px;
48
  border: 1px solid #000000;
49
  }
50
+
51
  .control-group label {
52
  display: block;
53
  margin-bottom: 10px;
 
56
  text-align: center;
57
  font-size: 14px;
58
  }
59
+
60
  .dimension-inputs {
61
  display: flex;
62
  gap: 10px;
63
  align-items: center;
64
  }
65
+
66
  .dimension-inputs input {
67
  width: 50px;
68
  padding: 8px;
 
71
  color: #000000;
72
  font-weight: bold;
73
  text-align: center;
74
+ font-family: 'Consolas', 'Courier New', monospace;
75
  }
76
+
77
  .dimension-inputs .label {
78
  font-size: 14px;
79
  color: #000000;
80
  margin: 0 5px;
81
  }
82
+
83
  .stats {
84
  display: flex;
85
  gap: 20px;
 
87
  flex-wrap: wrap;
88
  justify-content: center;
89
  }
90
+
91
  .stat-box {
92
  background: #ffffff;
93
  padding: 15px 20px;
 
95
  text-align: center;
96
  min-width: 120px;
97
  }
98
+
99
  .stat-box .label {
100
  font-size: 12px;
101
  margin-bottom: 8px;
 
103
  text-transform: uppercase;
104
  letter-spacing: 1px;
105
  }
106
+
107
  .stat-box .value {
108
  font-size: 24px;
109
  font-weight: bold;
110
  color: #000000;
111
  }
112
+
113
  .main-visualization {
114
  display: flex;
115
  gap: 40px;
116
  margin-bottom: 40px;
117
  }
118
+
119
  .cube-section {
120
  flex: 1;
121
  min-width: 600px;
122
  }
123
+
124
  .section-title {
125
  text-align: center;
126
  margin-bottom: 20px;
 
130
  border-bottom: 1px solid #000000;
131
  padding-bottom: 10px;
132
  }
133
+
134
  .cube-container {
135
  height: 500px;
136
  perspective: 1200px;
 
143
  cursor: grab;
144
  overflow: hidden;
145
  }
146
+
147
  .cube-container:active {
148
  cursor: grabbing;
149
  }
150
+
151
  .cube-3d {
152
  position: relative;
153
  transform-style: preserve-3d;
154
  transition: transform 0.1s ease-out;
155
  }
156
+
157
  .block-cube {
158
  position: absolute;
159
  width: 70px;
 
170
  text-align: center;
171
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
172
  }
173
+
174
  .block-cube:hover {
175
  background: #f0f0f0;
176
  border-width: 3px;
 
178
  z-index: 10;
179
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
180
  }
181
+
182
  .block-cube.selected {
183
  background: #000000;
184
  color: #ffffff;
 
186
  z-index: 5;
187
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
188
  }
189
+
190
  .block-label {
191
  font-size: 11px;
192
  line-height: 1.2;
 
195
  color: #000000;
196
  text-shadow: 0 0 2px rgba(255, 255, 255, 0.8);
197
  }
198
+
199
  .block-cube.selected .block-label {
200
  color: #ffffff;
201
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
202
  }
203
+
204
  .thread-count {
205
  font-size: 9px;
206
  color: #333333;
207
  font-weight: bold;
208
  text-shadow: 0 0 2px rgba(255, 255, 255, 0.8);
209
  }
210
+
211
  .block-cube.selected .thread-count {
212
  color: #cccccc;
213
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
214
  }
215
+
216
  .info-panel {
217
  flex: 0 0 350px;
218
  background: #ffffff;
 
221
  max-height: 600px;
222
  overflow-y: auto;
223
  }
224
+
225
  .info-title {
226
  font-size: 18px;
227
  font-weight: bold;
 
231
  border-bottom: 1px solid #000000;
232
  padding-bottom: 10px;
233
  }
234
+
235
  .info-item {
236
  margin-bottom: 20px;
237
  padding: 15px;
238
  background: #f8f8f8;
239
  border-left: 4px solid #000000;
240
  }
241
+
242
  .info-item .label {
243
  font-size: 12px;
244
  margin-bottom: 8px;
 
246
  text-transform: uppercase;
247
  letter-spacing: 1px;
248
  }
249
+
250
  .info-item .value {
251
  font-size: 16px;
252
  font-weight: bold;
253
  color: #000000;
254
  }
255
+
256
  .thread-detail-grid {
257
  display: grid;
258
+ grid-template-columns: repeat(auto-fit, minmax(26px, 1fr));
259
+ gap: 1px;
260
  margin-top: 15px;
261
+ padding: 12px;
262
  background: #f0f0f0;
263
  border: 1px solid #cccccc;
264
  }
265
+
266
  .thread-detail {
267
+ width: 24px;
268
+ height: 24px;
269
  background: #ffffff;
270
  border: 1px solid #000000;
271
  display: flex;
272
  align-items: center;
273
  justify-content: center;
274
+ font-size: 8px;
275
+ font-weight: bold;
276
  cursor: pointer;
277
  transition: all 0.2s ease;
278
  }
279
+
280
  .thread-detail:hover {
281
  background: #000000;
282
  color: #ffffff;
283
  transform: scale(1.2);
284
  }
285
+
286
  .thread-detail.selected {
287
  background: #000000;
288
  color: #ffffff;
289
  }
290
+
291
  .instructions {
292
  text-align: center;
293
  margin-top: 20px;
 
297
  padding: 15px;
298
  background: #f8f8f8;
299
  }
300
+
301
  .interaction-guide {
302
  display: flex;
303
  justify-content: space-around;
 
307
  border: 1px solid #cccccc;
308
  font-size: 12px;
309
  }
310
+
311
  .interaction-item {
312
  text-align: center;
313
  color: #333333;
314
  }
315
+
316
  .interaction-item .icon {
317
  font-size: 18px;
318
  margin-bottom: 5px;
319
  display: block;
320
  }
321
+
322
  .spatial-explanation {
323
  background: #f8f8f8;
324
  padding: 25px;
325
  border: 2px solid #000000;
326
  margin-bottom: 30px;
327
  }
328
+
329
  .spatial-explanation h3 {
330
  color: #000000;
331
  margin-bottom: 20px;
332
  border-bottom: 1px solid #000000;
333
  padding-bottom: 10px;
334
  }
335
+
336
+ .warp-visualization {
337
+ background: #ffffff;
338
+ border: 1px solid #000000;
339
+ padding: 20px;
340
+ margin: 20px 0;
341
+ display: flex;
342
+ flex-direction: column;
343
+ align-items: center;
344
+ }
345
+
346
+ .sm-representation {
347
+ background: #f0f0f0;
348
+ border: 2px solid #000000;
349
+ padding: 15px;
350
+ margin: 10px 0;
351
+ width: 100%;
352
+ max-width: 600px;
353
+ }
354
+
355
+ .sm-title {
356
+ font-weight: bold;
357
+ text-align: center;
358
+ margin-bottom: 15px;
359
+ font-size: 14px;
360
+ border-bottom: 1px solid #000000;
361
+ padding-bottom: 5px;
362
+ }
363
+
364
+ .warp-grid {
365
+ display: grid;
366
+ grid-template-columns: repeat(8, 1fr);
367
+ gap: 2px;
368
+ margin-bottom: 15px;
369
+ }
370
+
371
+ .warp-thread {
372
+ width: 20px;
373
+ height: 20px;
374
+ background: #ffffff;
375
+ border: 1px solid #000000;
376
+ display: flex;
377
+ align-items: center;
378
+ justify-content: center;
379
+ font-size: 8px;
380
+ font-weight: bold;
381
+ }
382
+
383
+ .warp-0 { background: #e0e0e0; }
384
+ .warp-1 { background: #d0d0d0; }
385
+ .warp-2 { background: #c0c0c0; }
386
+ .warp-3 { background: #b0b0b0; }
387
+
388
+ .warp-label {
389
+ font-size: 12px;
390
+ font-weight: bold;
391
+ margin-bottom: 5px;
392
+ text-align: center;
393
+ }
394
+
395
  .code-example {
396
  background: #f0f0f0;
397
  padding: 20px;
398
  border: 1px solid #cccccc;
399
+ font-family: 'Consolas', 'Courier New', monospace;
400
  font-size: 13px;
401
  line-height: 1.6;
402
  border-left: 4px solid #000000;
403
  margin: 15px 0;
404
  color: #000000;
405
  }
406
+
407
  .highlight {
408
  background: #e0e0e0;
409
  padding: 2px 4px;
410
  border: 1px solid #000000;
411
  }
412
+
413
+ .hardware-pipeline {
414
+ background: #ffffff;
415
+ border: 2px solid #000000;
416
+ padding: 20px;
417
+ margin: 20px 0;
418
+ }
419
+
420
+ .pipeline-stage {
421
+ margin-bottom: 30px;
422
+ border-bottom: 1px solid #cccccc;
423
+ padding-bottom: 20px;
424
+ }
425
+
426
+ .pipeline-stage h4 {
427
+ font-size: 16px;
428
+ font-weight: bold;
429
+ margin-bottom: 15px;
430
+ color: #000000;
431
+ border-bottom: 1px solid #000000;
432
+ padding-bottom: 8px;
433
+ }
434
+
435
+ .sm-array {
436
+ display: flex;
437
+ gap: 15px;
438
+ flex-wrap: wrap;
439
+ justify-content: center;
440
+ margin: 20px 0;
441
+ }
442
+
443
+ .sm-unit {
444
+ background: #f8f8f8;
445
+ border: 2px solid #000000;
446
+ padding: 15px;
447
+ min-width: 150px;
448
+ text-align: center;
449
+ }
450
+
451
+ .sm-header {
452
+ font-weight: bold;
453
+ font-size: 14px;
454
+ margin-bottom: 10px;
455
+ background: #000000;
456
+ color: #ffffff;
457
+ padding: 5px;
458
+ }
459
+
460
+ .block-assignment {
461
+ display: flex;
462
+ flex-direction: column;
463
+ gap: 5px;
464
+ }
465
+
466
+ .assigned-block {
467
+ background: #ffffff;
468
+ border: 1px solid #000000;
469
+ padding: 5px;
470
+ font-size: 11px;
471
+ font-weight: bold;
472
+ }
473
+
474
+ .sm-detailed {
475
+ background: #f8f8f8;
476
+ border: 2px solid #000000;
477
+ padding: 20px;
478
+ margin: 20px 0;
479
+ }
480
+
481
+ .sm-title {
482
+ font-size: 14px;
483
+ font-weight: bold;
484
+ text-align: center;
485
+ margin-bottom: 20px;
486
+ background: #000000;
487
+ color: #ffffff;
488
+ padding: 10px;
489
+ }
490
+
491
+ .sm-components {
492
+ display: flex;
493
+ flex-direction: column;
494
+ gap: 15px;
495
+ }
496
+
497
+ .scheduler-layer {
498
+ display: flex;
499
+ gap: 10px;
500
+ justify-content: center;
501
+ }
502
+
503
+ .scheduler-unit {
504
+ background: #d0d0d0;
505
+ border: 1px solid #000000;
506
+ padding: 8px 15px;
507
+ font-size: 11px;
508
+ font-weight: bold;
509
+ text-align: center;
510
+ min-width: 80px;
511
+ }
512
+
513
+ .register-layer {
514
+ display: flex;
515
+ gap: 10px;
516
+ justify-content: center;
517
+ }
518
+
519
+ .register-file {
520
+ background: #e0e0e0;
521
+ border: 1px solid #000000;
522
+ padding: 8px 15px;
523
+ font-size: 11px;
524
+ font-weight: bold;
525
+ text-align: center;
526
+ min-width: 80px;
527
+ }
528
+
529
+ .execution-layer {
530
+ display: flex;
531
+ gap: 8px;
532
+ justify-content: center;
533
+ flex-wrap: wrap;
534
+ }
535
+
536
+ .execution-unit {
537
+ border: 1px solid #000000;
538
+ padding: 8px 12px;
539
+ font-size: 10px;
540
+ font-weight: bold;
541
+ text-align: center;
542
+ min-width: 50px;
543
+ }
544
+
545
+ .execution-unit.int32 {
546
+ background: #f0f0f0;
547
+ }
548
+
549
+ .execution-unit.fp32 {
550
+ background: #e8e8e8;
551
+ }
552
+
553
+ .execution-unit.tensor {
554
+ background: #d8d8d8;
555
+ }
556
+
557
+ .execution-unit.ldst {
558
+ background: #c8c8c8;
559
+ }
560
+
561
+ .execution-unit.sfu {
562
+ background: #b8b8b8;
563
+ }
564
+
565
+ .memory-layer {
566
+ display: flex;
567
+ justify-content: center;
568
+ }
569
+
570
+ .shared-memory {
571
+ background: #000000;
572
+ color: #ffffff;
573
+ border: 2px solid #000000;
574
+ padding: 10px 20px;
575
+ font-size: 12px;
576
+ font-weight: bold;
577
+ text-align: center;
578
+ width: 80%;
579
+ }
580
+
581
+ .warp-flow {
582
+ display: flex;
583
+ gap: 30px;
584
+ align-items: flex-start;
585
+ margin: 20px 0;
586
+ }
587
+
588
+ .warp-scheduler {
589
+ background: #f8f8f8;
590
+ border: 2px solid #000000;
591
+ padding: 15px;
592
+ min-width: 200px;
593
+ }
594
+
595
+ .scheduler-title {
596
+ font-size: 14px;
597
+ font-weight: bold;
598
+ text-align: center;
599
+ margin-bottom: 15px;
600
+ background: #000000;
601
+ color: #ffffff;
602
+ padding: 8px;
603
+ }
604
+
605
+ .warp-queue {
606
+ display: flex;
607
+ flex-direction: column;
608
+ gap: 8px;
609
+ }
610
+
611
+ .warp-item {
612
+ padding: 8px 12px;
613
+ border: 1px solid #000000;
614
+ font-size: 11px;
615
+ font-weight: bold;
616
+ text-align: center;
617
+ }
618
+
619
+ .warp-item.active {
620
+ background: #000000;
621
+ color: #ffffff;
622
+ }
623
+
624
+ .warp-item.ready {
625
+ background: #d0d0d0;
626
+ }
627
+
628
+ .warp-item.waiting {
629
+ background: #f0f0f0;
630
+ }
631
+
632
+ .execution-pipeline {
633
+ flex: 1;
634
+ background: #f8f8f8;
635
+ border: 2px solid #000000;
636
+ padding: 15px;
637
+ }
638
+
639
+ .pipeline-step {
640
+ margin-bottom: 15px;
641
+ padding: 10px;
642
+ border: 1px solid #000000;
643
+ background: #ffffff;
644
+ }
645
+
646
+ .step-title {
647
+ font-size: 12px;
648
+ font-weight: bold;
649
+ margin-bottom: 5px;
650
+ color: #000000;
651
+ }
652
+
653
+ .step-content {
654
+ font-size: 11px;
655
+ color: #333333;
656
+ line-height: 1.4;
657
+ }
658
+
659
  .current-view {
660
  position: absolute;
661
  top: 10px;
 
668
  }
669
  </style>
670
  </head>
 
671
  <body>
672
  <div class="container">
673
  <h1>Interactive 3D GPU Threading</h1>
674
+
675
  <div class="controls">
676
  <div class="control-group">
677
  <label>Grid Dimensions (X × Y × Z)</label>
 
694
  </div>
695
  </div>
696
  </div>
697
+
698
  <div class="stats">
699
  <div class="stat-box">
700
  <div class="label">Total Blocks</div>
 
713
  <div class="value" id="spatialDims">3×2×2</div>
714
  </div>
715
  </div>
716
+
717
  <div class="interaction-guide">
718
  <div class="interaction-item">
719
  <span class="icon">🖱️</span>
 
732
  <div>Double-Click to Reset View</div>
733
  </div>
734
  </div>
735
+
736
  <div class="main-visualization">
737
  <div class="cube-section">
738
  <div class="section-title">Interactive 3D Block Grid</div>
739
+
740
  <div class="cube-container" id="cubeContainer">
741
  <div class="cube-3d" id="cube3d"></div>
742
  <div class="current-view" id="currentView">
743
  Rotation: X=15° Y=25° | Zoom: 1.0x
744
  </div>
745
  </div>
746
+
747
  <div class="instructions">
748
+ Drag to rotate the cube and explore 3D spatial relationships • Scroll to zoom in/out • Click blocks to examine their threads • Double-click to reset view
 
749
  </div>
750
  </div>
751
+
752
  <div class="info-panel">
753
  <div class="info-title">Block & Thread Details</div>
754
  <div id="blockInfo">
755
+ <div style="text-align: center; color: #666666; padding: 25px; border: 1px solid #cccccc; background: #f8f8f8;">
756
+ Rotate the cube to explore spatial relationships, then click on any block to see its thread organization and understand how neighboring blocks relate to each other in 3D space.
 
 
757
  </div>
758
  </div>
759
  </div>
760
  </div>
761
+
762
  <div class="spatial-explanation">
763
  <h3>Understanding Spatial Relationships Through Direct Manipulation</h3>
764
+ <p>The ability to directly manipulate the 3D cube with your cursor creates a much deeper understanding of spatial relationships than static views or sliders ever could. As you rotate the cube, you can see exactly which blocks are neighbors and how the grid extends in all three dimensions simultaneously.</p>
765
+
 
 
766
  <p><strong>Why Direct Interaction Builds Better Mental Models:</strong></p>
767
+ <p>When you drag to rotate the cube, your brain naturally builds a spatial mental model that connects the visual structure to the mathematical relationships. You can see how a block at position [1,0,1] relates spatially to blocks at [0,0,1], [2,0,1], [1,1,1], and [1,0,0]. This spatial understanding is crucial for writing efficient GPU code that takes advantage of memory locality and thread cooperation patterns.</p>
768
+
769
+ <p><strong>Learning Exercise:</strong> Try rotating the cube to view it from different angles while thinking about how data flows through your algorithm. Can you identify which blocks would naturally work together on shared data? The spatial arrangement you see directly represents the memory access patterns that will determine your algorithm's performance.</p>
770
+
 
 
 
 
 
 
771
  <div class="code-example">
772
+ // Example: 3D convolution filter processing
773
+ fn apply_3d_convolution(input: UnsafePointer[Float32], output: UnsafePointer[Float32],
774
+ width: Int, height: Int, depth: Int):
775
+ // Each thread processes one output voxel
776
+ let <span class="highlight">x = global_idx.x</span> // Width position
777
+ let <span class="highlight">y = global_idx.y</span> // Height position
778
+ let <span class="highlight">z = global_idx.z</span> // Depth position
779
+
780
+ if x < width and y < height and z < depth:
781
+ var sum: Float32 = 0
782
+
783
+ // Access neighboring voxels for convolution
784
+ for dz in range(-1, 2):
785
+ for dy in range(-1, 2):
786
+ for dx in range(-1, 2):
787
+ let nx = x + dx
788
+ let ny = y + dy
789
+ let nz = z + dz
790
+
791
+ if nx >= 0 and nx < width and ny >= 0 and ny < height and nz >= 0 and nz < depth:
792
+ let neighbor_idx = nz * width * height + ny * width + nx
793
+ sum += input[neighbor_idx] * filter_weights[dz+1][dy+1][dx+1]
794
+
795
+ let output_idx = z * width * height + y * width + x
796
+ output[output_idx] = sum
797
  </div>
798
+
799
+ <p>In this convolution example, threads processing nearby voxels (which you can see as spatially close when you rotate the cube) will access overlapping sets of input data. The 3D spatial organization ensures that these threads are grouped into nearby blocks, enabling efficient sharing of cached memory containing the input voxels they all need to access.</p>
800
  </div>
801
+ </div>
802
+
803
+ <script>
804
+ let selectedBlock = null;
805
+ let selectedThread = null;
806
+ let isMouseDown = false;
807
+ let lastMouseX = 0;
808
+ let lastMouseY = 0;
809
+ let rotationX = 15;
810
+ let rotationY = 25;
811
+ let zoom = 1.0;
812
+
813
+ function updateVisualization() {
814
+ const gridX = parseInt(document.getElementById('gridX').value);
815
+ const gridY = parseInt(document.getElementById('gridY').value);
816
+ const gridZ = parseInt(document.getElementById('gridZ').value);
817
+ const blockX = parseInt(document.getElementById('blockX').value);
818
+ const blockY = parseInt(document.getElementById('blockY').value);
819
+ const blockZ = parseInt(document.getElementById('blockZ').value);
820
+
821
+ const totalBlocks = gridX * gridY * gridZ;
822
+ const threadsPerBlock = blockX * blockY * blockZ;
823
+ const totalThreads = totalBlocks * threadsPerBlock;
824
+
825
+ // Update stats
826
+ document.getElementById('totalBlocks').textContent = totalBlocks;
827
+ document.getElementById('threadsPerBlock').textContent = threadsPerBlock;
828
+ document.getElementById('totalThreads').textContent = totalThreads;
829
+ document.getElementById('spatialDims').textContent = `${gridX}×${gridY}×${gridZ}`;
830
+
831
+ create3DCube();
832
+ selectedBlock = null;
833
+ selectedThread = null;
834
+ updateBlockInfo();
835
+ }
836
+
837
+ function create3DCube() {
838
+ const gridX = parseInt(document.getElementById('gridX').value);
839
+ const gridY = parseInt(document.getElementById('gridY').value);
840
+ const gridZ = parseInt(document.getElementById('gridZ').value);
841
+ const blockX = parseInt(document.getElementById('blockX').value);
842
+ const blockY = parseInt(document.getElementById('blockY').value);
843
+ const blockZ = parseInt(document.getElementById('blockZ').value);
844
+
845
+ const cube3d = document.getElementById('cube3d');
846
+ cube3d.innerHTML = '';
847
+
848
+ const spacing = 80; // Space between blocks
849
+
850
+ // Create all blocks in 3D space
851
+ for (let z = 0; z < gridZ; z++) {
852
+ for (let y = 0; y < gridY; y++) {
853
+ for (let x = 0; x < gridX; x++) {
854
+ const block = createBlock3D(x, y, z, blockX, blockY, blockZ, spacing);
855
+ cube3d.appendChild(block);
856
  }
857
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
858
  }
859
+
860
+ updateCubeTransform();
861
+ }
862
+
863
+ function createBlock3D(blockX_idx, blockY_idx, blockZ_idx, blockDimX, blockDimY, blockDimZ, spacing) {
864
+ const block = document.createElement('div');
865
+ block.className = 'block-cube';
866
+
867
+ // Calculate center offset for better visual balance
868
+ const gridX = parseInt(document.getElementById('gridX').value);
869
+ const gridY = parseInt(document.getElementById('gridY').value);
870
+ const gridZ = parseInt(document.getElementById('gridZ').value);
871
+
872
+ const centerOffsetX = (gridX - 1) * spacing / 2;
873
+ const centerOffsetY = (gridY - 1) * spacing / 2;
874
+ const centerOffsetZ = (gridZ - 1) * spacing / 2;
875
+
876
+ // Position in 3D space
877
+ const translateX = blockX_idx * spacing - centerOffsetX;
878
+ const translateY = blockY_idx * spacing - centerOffsetY;
879
+ const translateZ = blockZ_idx * spacing - centerOffsetZ;
880
+
881
+ block.style.transform = `translate3d(${translateX}px, ${translateY}px, ${translateZ}px)`;
882
+
883
+ // Block content
884
+ const label = document.createElement('div');
885
+ label.className = 'block-label';
886
+ label.textContent = `[${blockX_idx},${blockY_idx},${blockZ_idx}]`;
887
+ block.appendChild(label);
888
+
889
+ const threadCount = document.createElement('div');
890
+ threadCount.className = 'thread-count';
891
+ threadCount.textContent = `${blockDimX}×${blockDimY}×${blockDimZ}`;
892
+ block.appendChild(threadCount);
893
+
894
+ // Click handler
895
+ block.addEventListener('click', (e) => {
896
+ e.stopPropagation();
897
+
898
+ // Remove previous selection
899
+ document.querySelectorAll('.block-cube.selected').forEach(b => b.classList.remove('selected'));
900
+
901
+ // Select this block
902
+ block.classList.add('selected');
903
+ selectedBlock = {
904
+ idx: { x: blockX_idx, y: blockY_idx, z: blockZ_idx },
905
+ dim: { x: blockDimX, y: blockDimY, z: blockDimZ }
906
+ };
907
+
908
+ updateBlockInfo();
909
+ });
910
+
911
+ return block;
912
+ }
913
+
914
+ function updateCubeTransform() {
915
+ const cube3d = document.getElementById('cube3d');
916
+ cube3d.style.transform = `scale(${zoom}) rotateX(${rotationX}deg) rotateY(${rotationY}deg)`;
917
+
918
+ // Update current view display
919
+ document.getElementById('currentView').textContent =
920
+ `Rotation: X=${rotationX}° Y=${rotationY}° | Zoom: ${zoom.toFixed(1)}x`;
921
+ }
922
+
923
+ function updateBlockInfo() {
924
+ const blockInfo = document.getElementById('blockInfo');
925
+
926
+ if (!selectedBlock) {
927
+ blockInfo.innerHTML = `
928
  <div style="text-align: center; color: #666666; padding: 25px; border: 1px solid #cccccc; background: #f8f8f8;">
929
  Rotate the cube to explore spatial relationships, then click on any block to see its thread organization and understand how neighboring blocks relate to each other in 3D space.
930
  </div>
931
  `;
932
+ return;
933
+ }
934
+
935
+ const b = selectedBlock;
936
+ const threadsPerBlock = b.dim.x * b.dim.y * b.dim.z;
937
+ const warpSize = 32; // Standard warp size for modern GPUs
938
+ const numWarps = Math.ceil(threadsPerBlock / warpSize);
939
+
940
+ // Calculate spatial neighbors
941
+ const gridX = parseInt(document.getElementById('gridX').value);
942
+ const gridY = parseInt(document.getElementById('gridY').value);
943
+ const gridZ = parseInt(document.getElementById('gridZ').value);
944
+
945
+ const neighbors = [];
946
+ const directions = [
947
+ { dx: -1, dy: 0, dz: 0, name: 'left' },
948
+ { dx: 1, dy: 0, dz: 0, name: 'right' },
949
+ { dx: 0, dy: -1, dz: 0, name: 'back' },
950
+ { dx: 0, dy: 1, dz: 0, name: 'front' },
951
+ { dx: 0, dy: 0, dz: -1, name: 'below' },
952
+ { dx: 0, dy: 0, dz: 1, name: 'above' }
953
+ ];
954
+
955
+ directions.forEach(dir => {
956
+ const nx = b.idx.x + dir.dx;
957
+ const ny = b.idx.y + dir.dy;
958
+ const nz = b.idx.z + dir.dz;
959
+
960
+ if (nx >= 0 && nx < gridX && ny >= 0 && ny < gridY && nz >= 0 && nz < gridZ) {
961
+ neighbors.push(`[${nx}, ${ny}, ${nz}] (${dir.name})`);
962
  }
963
+ });
964
+
965
+ blockInfo.innerHTML = `
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
966
  <div class="info-item">
967
  <div class="label">Selected Block</div>
968
  <div class="value">Block [${b.idx.x}, ${b.idx.y}, ${b.idx.z}]</div>
 
974
  </div>
975
 
976
  <div class="info-item">
977
+ <div class="label">Warp Organization</div>
978
+ <div class="value">${numWarps} warp${numWarps > 1 ? 's' : ''} (${warpSize} threads each)</div>
979
+ </div>
980
+
981
+ <div style="margin-top: 20px; padding: 15px; background: #f0f0f0; border-left: 4px solid #000000;">
982
+ <div style="font-size: 12px; color: #333333; line-height: 1.6;">
983
+ <strong>SM Execution:</strong> When this block is assigned to a Streaming Multiprocessor (SM), it will be divided into ${numWarps} warp${numWarps > 1 ? 's' : ''}. ${numWarps === 1 ? 'All threads will execute in perfect synchronization.' : `The first ${numWarps - 1} warp${numWarps > 2 ? 's' : ''} will have ${warpSize} threads each, and the last warp will have ${threadsPerBlock % warpSize || warpSize} threads.`}
984
+ </div>
985
  </div>
986
 
987
  <div style="margin-top: 20px;">
 
999
 
1000
  <div style="margin-top: 15px; padding: 15px; background: #e8e8e8; border: 1px solid #cccccc;">
1001
  <div style="font-size: 11px; color: #333333;">
1002
+ 💡 <strong>Performance Insight:</strong> Neighboring blocks (visible when you rotate the cube) are often assigned to nearby SMs, enabling efficient data sharing through the GPU's memory hierarchy. This spatial locality is crucial for achieving optimal memory bandwidth utilization.
1003
  </div>
1004
  </div>
1005
  `;
1006
+
1007
+ createThreadGrid();
1008
+ }
1009
+
1010
+ function createWarpVisualization() {
1011
+ const warpDemo = document.getElementById('warpDemo');
1012
+ if (!warpDemo) return;
1013
+
1014
+ warpDemo.innerHTML = '';
1015
+
1016
+ // Create 32 threads representing one warp
1017
+ for (let i = 0; i < 32; i++) {
1018
+ const thread = document.createElement('div');
1019
+ thread.className = 'warp-thread warp-0';
1020
+ thread.textContent = i;
1021
+ thread.title = `Thread ${i} in Warp 0`;
1022
+ warpDemo.appendChild(thread);
1023
  }
1024
+ }
1025
+
1026
+ function createThreadGrid() {
1027
+ if (!selectedBlock) return;
1028
+
1029
+ const threadGrid = document.getElementById('threadGrid');
1030
+ if (!threadGrid) return;
1031
+
1032
+ threadGrid.innerHTML = '';
1033
+
1034
+ const b = selectedBlock;
1035
+ const maxThreadsToShow = 64; // Limit for visual clarity
1036
+ const totalThreads = b.dim.x * b.dim.y * b.dim.z;
1037
+
1038
+ if (totalThreads > maxThreadsToShow) {
1039
+ threadGrid.innerHTML = `
1040
  <div style="text-align: center; padding: 20px; color: #666666;">
1041
  Too many threads to display (${totalThreads} total)<br>
1042
  Try smaller block dimensions to see individual threads
1043
  </div>
1044
  `;
1045
+ return;
1046
+ }
1047
+
1048
+ threadGrid.style.gridTemplateColumns = `repeat(${Math.min(b.dim.x, 8)}, 1fr)`;
1049
+
1050
+ // Create threads for visualization
1051
+ for (let z = 0; z < Math.min(b.dim.z, 4); z++) { // Show max 4 Z layers
1052
+ for (let y = 0; y < b.dim.y; y++) {
1053
+ for (let x = 0; x < b.dim.x; x++) {
1054
+ const thread = document.createElement('div');
1055
+ thread.className = 'thread-detail';
1056
+ thread.textContent = `${x},${y},${z}`;
1057
+ thread.title = `Thread [${x}, ${y}, ${z}] in Block [${b.idx.x}, ${b.idx.y}, ${b.idx.z}]`;
1058
+
1059
+ // Calculate global position
1060
+ const globalX = b.dim.x * b.idx.x + x;
1061
+ const globalY = b.dim.y * b.idx.y + y;
1062
+ const globalZ = b.dim.z * b.idx.z + z;
1063
+
1064
+ thread.addEventListener('click', () => {
1065
+ document.querySelectorAll('.thread-detail.selected').forEach(t => t.classList.remove('selected'));
1066
+ thread.classList.add('selected');
1067
+
1068
+ selectedThread = {
1069
+ blockIdx: b.idx,
1070
+ threadIdx: { x, y, z },
1071
+ globalIdx: { x: globalX, y: globalY, z: globalZ },
1072
+ blockDim: b.dim
1073
+ };
1074
+
1075
+ showThreadDetails();
1076
+ });
1077
+
1078
+ threadGrid.appendChild(thread);
 
1079
  }
1080
  }
1081
  }
1082
+ }
1083
+
1084
+ function showThreadDetails() {
1085
+ if (!selectedThread) return;
1086
+
1087
+ const t = selectedThread;
1088
+ const details = `
1089
  <div style="margin-top: 20px; padding: 15px; background: #e8e8e8; border: 1px solid #000000;">
1090
  <div style="font-size: 12px; font-weight: bold; margin-bottom: 10px;">Selected Thread Details:</div>
1091
  <div style="font-size: 11px; line-height: 1.6;">
 
1099
  </div>
1100
  </div>
1101
  `;
1102
+
1103
+ const blockInfo = document.getElementById('blockInfo');
1104
+ // Remove existing thread details
1105
+ const existing = blockInfo.querySelector('.thread-details');
1106
+ if (existing) existing.remove();
1107
+
1108
+ const detailsDiv = document.createElement('div');
1109
+ detailsDiv.className = 'thread-details';
1110
+ detailsDiv.innerHTML = details;
1111
+ blockInfo.appendChild(detailsDiv);
1112
+ }
1113
+
1114
+ // Mouse interaction setup
1115
+ function setupMouseInteraction() {
1116
+ const cubeContainer = document.getElementById('cubeContainer');
1117
+
1118
+ // Mouse down event
1119
+ cubeContainer.addEventListener('mousedown', (e) => {
1120
+ isMouseDown = true;
1121
+ lastMouseX = e.clientX;
1122
+ lastMouseY = e.clientY;
1123
+ cubeContainer.style.cursor = 'grabbing';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1124
  });
1125
+
1126
+ // Mouse move event
1127
+ document.addEventListener('mousemove', (e) => {
1128
+ if (!isMouseDown) return;
1129
+
1130
+ const deltaX = e.clientX - lastMouseX;
1131
+ const deltaY = e.clientY - lastMouseY;
1132
+
1133
+ // Update rotation based on mouse movement
1134
+ rotationY += deltaX * 0.5; // Horizontal movement controls Y rotation
1135
+ rotationX -= deltaY * 0.5; // Vertical movement controls X rotation (inverted for natural feel)
1136
+
1137
+ // Constrain rotations to reasonable ranges
1138
+ rotationX = Math.max(-90, Math.min(90, rotationX));
1139
+
1140
+ updateCubeTransform();
1141
+
1142
+ lastMouseX = e.clientX;
1143
+ lastMouseY = e.clientY;
1144
+ });
1145
+
1146
+ // Mouse up event
1147
+ document.addEventListener('mouseup', () => {
1148
+ isMouseDown = false;
1149
+ cubeContainer.style.cursor = 'grab';
1150
+ });
1151
+
1152
+ // Mouse wheel event for zooming
1153
+ cubeContainer.addEventListener('wheel', (e) => {
1154
+ e.preventDefault();
1155
+
1156
+ const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
1157
+ zoom *= zoomFactor;
1158
+ zoom = Math.max(0.3, Math.min(3.0, zoom)); // Constrain zoom range
1159
+
1160
+ updateCubeTransform();
1161
+ });
1162
+
1163
+ // Double-click to reset view
1164
+ cubeContainer.addEventListener('dblclick', () => {
1165
+ rotationX = 15;
1166
+ rotationY = 25;
1167
+ zoom = 1.0;
1168
+ updateCubeTransform();
1169
+ });
1170
+
1171
+ // Prevent context menu on right-click
1172
+ cubeContainer.addEventListener('contextmenu', (e) => {
1173
+ e.preventDefault();
1174
+ });
1175
+ }
1176
+
1177
+ // Event listeners for dimension controls
1178
+ ['gridX', 'gridY', 'gridZ', 'blockX', 'blockY', 'blockZ'].forEach(id => {
1179
+ document.getElementById(id).addEventListener('input', updateVisualization);
1180
+ });
1181
+
1182
+ // Initialize everything
1183
+ setupMouseInteraction();
1184
+ updateVisualization();
1185
+ createWarpVisualization();
1186
+ </script>
1187
  </body>
 
1188
  </html>