Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>CUDA Grid Visualizer</title> | |
| <style> | |
| :root { | |
| --bg-color: #121212; | |
| --text-color: #e0e0e0; | |
| --input-bg: #2a2a2a; | |
| --input-text: #ffffff; | |
| --grid-bg: #1e272e; | |
| --thread-bg: #34495e; | |
| --thread-hover: #3498db; | |
| --info-bg: #1a2327; | |
| } | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| padding: 20px; | |
| background-color: var(--bg-color); | |
| color: var(--text-color); | |
| transition: all 0.3s ease; | |
| min-height: 100vh; | |
| margin: 0; | |
| } | |
| h1 { | |
| margin-bottom: 20px; | |
| font-size: 2.5em; | |
| text-align: center; | |
| color: #3498db; | |
| } | |
| #controls { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 20px; | |
| margin-bottom: 30px; | |
| justify-content: center; | |
| background-color: var(--input-bg); | |
| padding: 20px; | |
| border-radius: 10px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .input-group { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| label { | |
| margin-bottom: 8px; | |
| font-size: 1em; | |
| color: #3498db; | |
| } | |
| input { | |
| width: 70px; | |
| padding: 10px; | |
| border: none; | |
| border-radius: 5px; | |
| background-color: var(--input-bg); | |
| color: var(--input-text); | |
| text-align: center; | |
| font-size: 1.1em; | |
| transition: all 0.3s ease; | |
| } | |
| input:focus { | |
| outline: none; | |
| box-shadow: 0 0 0 2px #3498db; | |
| } | |
| #grid-container { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 2px; | |
| background-color: var(--grid-bg); | |
| padding: 4px; | |
| border-radius: 10px; | |
| box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); | |
| max-width: 90vw; | |
| justify-content: flex-start; | |
| } | |
| .thread { | |
| width: 30px; | |
| height: 30px; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| font-size: 0.9em; | |
| cursor: pointer; | |
| border-radius: 4px; | |
| transition: all 0.2s ease; | |
| } | |
| .thread:hover { | |
| transform: scale(1.1); | |
| z-index: 1; | |
| } | |
| #info-panel { | |
| margin-top: 30px; | |
| padding: 20px; | |
| background-color: var(--info-bg); | |
| border-radius: 10px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| max-width: 350px; | |
| width: 100%; | |
| } | |
| #info-panel p { | |
| margin: 10px 0; | |
| font-size: 1em; | |
| } | |
| #info-panel strong { | |
| color: #3498db; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>CUDA Grid Visualizer</h1> | |
| <div id="controls"> | |
| <div class="input-group"> | |
| <label for="num-blocks">Number of Blocks</label> | |
| <input type="number" id="num-blocks" value="4" min="1" max="64"> | |
| </div> | |
| <div class="input-group"> | |
| <label for="num-threads">Threads per Block</label> | |
| <input type="number" id="num-threads" value="16" min="1" max="1024"> | |
| </div> | |
| <div class="input-group"> | |
| <label for="grid-width">Grid Width (threads)</label> | |
| <input type="number" id="grid-width" value="32" min="1" max="256"> | |
| </div> | |
| </div> | |
| <div id="grid-container"></div> | |
| <div id="info-panel"></div> | |
| <script> | |
| function updateGrid() { | |
| const numBlocks = parseInt(document.getElementById('num-blocks').value); | |
| const numThreads = parseInt(document.getElementById('num-threads').value); | |
| const gridWidth = parseInt(document.getElementById('grid-width').value); | |
| const gridContainer = document.getElementById('grid-container'); | |
| gridContainer.innerHTML = ''; | |
| gridContainer.style.width = `${gridWidth * 32}px`; // 30px thread width + 2px gap | |
| // Generate a list of distinct colors for blocks | |
| const blockColors = generateBlockColors(numBlocks); | |
| for (let blockIdx = 0; blockIdx < numBlocks; blockIdx++) { | |
| for (let threadIdx = 0; threadIdx < numThreads; threadIdx++) { | |
| const thread = document.createElement('div'); | |
| thread.className = 'thread'; | |
| thread.textContent = threadIdx; | |
| thread.style.backgroundColor = blockColors[blockIdx]; | |
| thread.addEventListener('mouseover', () => showInfo(blockIdx, threadIdx, numThreads)); | |
| thread.addEventListener('mouseout', clearInfo); | |
| gridContainer.appendChild(thread); | |
| } | |
| } | |
| } | |
| function generateBlockColors(numBlocks) { | |
| const colors = []; | |
| for (let i = 0; i < numBlocks; i++) { | |
| const hue = (i * 137.5) % 360; // Use golden angle approximation for distribution | |
| colors.push(`hsl(${hue}, 70%, 60%)`); | |
| } | |
| return colors; | |
| } | |
| function showInfo(blockIdx, threadIdx, numThreads) { | |
| const globalThreadId = blockIdx * numThreads + threadIdx; | |
| const infoPanel = document.getElementById('info-panel'); | |
| infoPanel.innerHTML = ` | |
| <p><strong>Block Index:</strong> ${blockIdx}</p> | |
| <p><strong>Thread Index in Block:</strong> ${threadIdx}</p> | |
| <p><strong>Global Thread ID:</strong> ${globalThreadId}</p> | |
| `; | |
| } | |
| function clearInfo() { | |
| document.getElementById('info-panel').innerHTML = ''; | |
| } | |
| function debounce(func, wait) { | |
| let timeout; | |
| return function executedFunction(...args) { | |
| const later = () => { | |
| clearTimeout(timeout); | |
| func(...args); | |
| }; | |
| clearTimeout(timeout); | |
| timeout = setTimeout(later, wait); | |
| }; | |
| } | |
| const debouncedUpdateGrid = debounce(updateGrid, 300); | |
| document.querySelectorAll('input').forEach(input => { | |
| input.addEventListener('input', debouncedUpdateGrid); | |
| }); | |
| updateGrid(); | |
| </script> | |
| </body> | |
| </html> | |