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> | |