Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>GPU Pooling Algorithm</title> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| background: #ffffff; | |
| color: #000000; | |
| font-family: 'Consolas', 'Monaco', 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace; | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| padding: 20px; | |
| } | |
| .container { | |
| max-width: 800px; | |
| width: 100%; | |
| padding: 0 10px; | |
| } | |
| .title { | |
| text-align: center; | |
| font-size: 1.8rem; | |
| margin-bottom: 20px; | |
| color: #000000; | |
| font-weight: 400; | |
| letter-spacing: 1px; | |
| } | |
| .section { | |
| margin: 15px 0; | |
| position: relative; | |
| } | |
| .section-title { | |
| text-align: center; | |
| font-size: 1.1rem; | |
| margin-bottom: 10px; | |
| color: #000000; | |
| font-weight: 500; | |
| } | |
| .array-container { | |
| display: flex; | |
| justify-content: center; | |
| gap: 4px; | |
| margin: 15px 0; | |
| flex-wrap: wrap; | |
| } | |
| .array-element { | |
| width: 50px; | |
| height: 40px; | |
| border: 2px solid #000000; | |
| border-radius: 4px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 10px; | |
| font-weight: 500; | |
| background: #ffffff; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| text-align: center; | |
| line-height: 1; | |
| } | |
| .array-element .value { | |
| font-size: 12px; | |
| font-weight: 600; | |
| margin-bottom: 2px; | |
| } | |
| .array-element .label { | |
| font-size: 8px; | |
| color: #666; | |
| font-weight: 400; | |
| } | |
| .array-element.highlight { | |
| background: #f0f0f0; | |
| border-color: #000000; | |
| border-width: 3px; | |
| transform: scale(1.05); | |
| } | |
| .array-element.processing { | |
| background: #e0e0e0; | |
| border-color: #666666; | |
| border-width: 3px; | |
| } | |
| .block-container { | |
| background: #f8f8f8; | |
| border: 2px solid #000000; | |
| border-radius: 6px; | |
| padding: 15px; | |
| margin: 20px 0; | |
| } | |
| .threads-container { | |
| display: flex; | |
| justify-content: center; | |
| gap: 4px; | |
| margin: 15px 0; | |
| flex-wrap: wrap; | |
| } | |
| .thread { | |
| width: 50px; | |
| height: 40px; | |
| border: 2px solid #666666; | |
| border-radius: 4px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 11px; | |
| background: #ffffff; | |
| transition: all 0.3s ease; | |
| } | |
| .thread.active { | |
| background: #d0d0d0; | |
| border-color: #000000; | |
| border-width: 3px; | |
| } | |
| .barrier { | |
| width: 100%; | |
| height: 2px; | |
| background: repeating-linear-gradient( | |
| 90deg, | |
| #000000 0px, | |
| #000000 8px, | |
| transparent 8px, | |
| transparent 16px | |
| ); | |
| margin: 15px 0; | |
| position: relative; | |
| } | |
| .barrier::after { | |
| content: "Barrier"; | |
| position: absolute; | |
| right: 0; | |
| top: -20px; | |
| color: #000000; | |
| font-size: 12px; | |
| font-weight: 500; | |
| } | |
| .shared-memory { | |
| background: #f0f0f0; | |
| border: 2px solid #333333; | |
| border-radius: 4px; | |
| padding: 15px; | |
| margin: 15px 0; | |
| } | |
| .memory-info { | |
| text-align: center; | |
| margin-bottom: 10px; | |
| color: #000000; | |
| font-weight: 500; | |
| font-size: 12px; | |
| } | |
| .memory-elements { | |
| display: flex; | |
| justify-content: center; | |
| gap: 3px; | |
| flex-wrap: wrap; | |
| } | |
| .memory-element { | |
| width: 40px; | |
| height: 30px; | |
| border: 1px solid #666666; | |
| border-radius: 3px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 9px; | |
| background: #ffffff; | |
| transition: all 0.3s ease; | |
| } | |
| .window-highlight { | |
| background: #e0e0e0; | |
| border-color: #000000; | |
| border-width: 2px; | |
| } | |
| .window-info { | |
| text-align: center; | |
| margin: 8px 0; | |
| color: #333333; | |
| font-weight: 500; | |
| font-size: 11px; | |
| } | |
| .output-container { | |
| border: 2px solid #000000; | |
| border-radius: 6px; | |
| padding: 20px; | |
| } | |
| .controls { | |
| text-align: center; | |
| margin: 30px 0; | |
| } | |
| .btn { | |
| background: #000000; | |
| border: 2px solid #000000; | |
| padding: 12px 30px; | |
| border-radius: 4px; | |
| color: white; | |
| font-size: 16px; | |
| cursor: pointer; | |
| margin: 0 10px; | |
| transition: all 0.3s ease; | |
| font-weight: 500; | |
| } | |
| .btn:hover { | |
| background: #333333; | |
| transform: translateY(-1px); | |
| } | |
| .btn:active { | |
| transform: translateY(0); | |
| } | |
| .connection-line { | |
| position: absolute; | |
| background: #000000; | |
| height: 2px; | |
| opacity: 0; | |
| transition: opacity 0.5s ease; | |
| } | |
| .connection-line.show { | |
| opacity: 1; | |
| } | |
| .stats { | |
| display: flex; | |
| justify-content: space-around; | |
| margin: 20px 0; | |
| padding: 15px; | |
| background: #f8f8f8; | |
| border: 1px solid #cccccc; | |
| border-radius: 6px; | |
| } | |
| .stat { | |
| text-align: center; | |
| } | |
| .stat-value { | |
| font-size: 1.5rem; | |
| color: #000000; | |
| font-weight: 600; | |
| } | |
| .stat-label { | |
| font-size: 0.9rem; | |
| color: #666666; | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| } | |
| .processing { | |
| animation: pulse 1s infinite; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1 class="title">GPU Pooling Algorithm</h1> | |
| <div class="stats"> | |
| <div class="stat"> | |
| <div class="stat-value" id="window-size">3</div> | |
| <div class="stat-label">Window Size</div> | |
| </div> | |
| <div class="stat"> | |
| <div class="stat-value" id="threads-count">8</div> | |
| <div class="stat-label">Threads</div> | |
| </div> | |
| <div class="stat"> | |
| <div class="stat-value" id="current-step">0</div> | |
| <div class="stat-label">Current Step</div> | |
| </div> | |
| </div> | |
| <div class="section"> | |
| <div class="section-title">Input Array (size=8)</div> | |
| <div class="array-container" id="input-array"> | |
| <!-- Generated dynamically --> | |
| </div> | |
| </div> | |
| <div class="block-container"> | |
| <div class="section-title">Block 0</div> | |
| <div class="threads-container" id="threads"> | |
| <!-- Generated dynamically --> | |
| </div> | |
| <div class="barrier"></div> | |
| <div class="shared-memory"> | |
| <div class="memory-info"> | |
| Shared Memory (TPB=8) • <span style="color: #333333; font-weight: 600;">Parallel Processing</span> | |
| </div> | |
| <div class="window-info">Sum Pooling (Window=3)</div> | |
| <div class="memory-elements" id="shared-memory"> | |
| <!-- Generated dynamically --> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="section output-container"> | |
| <div class="section-title">Output Array (size=8)</div> | |
| <div class="array-container" id="output-array"> | |
| <!-- Generated dynamically --> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const ARRAY_SIZE = 8; | |
| const WINDOW_SIZE = 3; | |
| let currentStep = 0; | |
| let animationInterval; | |
| // Sample input data | |
| const inputData = [1.2, 2.8, 0.5, 3.1, 1.9, 2.3, 0.8, 1.7]; | |
| function initializeVisualization() { | |
| createInputArray(); | |
| createThreads(); | |
| createSharedMemory(); | |
| createOutputArray(); | |
| startLoopingAnimation(); | |
| } | |
| function createInputArray() { | |
| const container = document.getElementById('input-array'); | |
| container.innerHTML = ''; | |
| for (let i = 0; i < ARRAY_SIZE; i++) { | |
| const element = document.createElement('div'); | |
| element.className = 'array-element'; | |
| element.innerHTML = `<div class="value">${inputData[i]}</div><div class="label">a[${i}]</div>`; | |
| element.id = `input-${i}`; | |
| element.title = `a[${i}] = ${inputData[i]}`; | |
| container.appendChild(element); | |
| } | |
| } | |
| function createThreads() { | |
| const container = document.getElementById('threads'); | |
| container.innerHTML = ''; | |
| for (let i = 0; i < ARRAY_SIZE; i++) { | |
| const thread = document.createElement('div'); | |
| thread.className = 'thread'; | |
| thread.textContent = `T${i}`; | |
| thread.id = `thread-${i}`; | |
| container.appendChild(thread); | |
| } | |
| } | |
| function createSharedMemory() { | |
| const container = document.getElementById('shared-memory'); | |
| container.innerHTML = ''; | |
| for (let i = 0; i < ARRAY_SIZE; i++) { | |
| const element = document.createElement('div'); | |
| element.className = 'memory-element'; | |
| element.textContent = `data[${i}]`; | |
| element.id = `memory-${i}`; | |
| container.appendChild(element); | |
| } | |
| } | |
| function createOutputArray() { | |
| const container = document.getElementById('output-array'); | |
| container.innerHTML = ''; | |
| for (let i = 0; i < ARRAY_SIZE; i++) { | |
| const element = document.createElement('div'); | |
| element.className = 'array-element'; | |
| element.textContent = `out[${i}]`; | |
| element.id = `output-${i}`; | |
| container.appendChild(element); | |
| } | |
| } | |
| function clearHighlights() { | |
| document.querySelectorAll('.highlight, .processing, .active, .window-highlight').forEach(el => { | |
| el.classList.remove('highlight', 'processing', 'active', 'window-highlight'); | |
| }); | |
| } | |
| function highlightWindow(threadId) { | |
| clearHighlights(); | |
| // Highlight active thread | |
| document.getElementById(`thread-${threadId}`).classList.add('active'); | |
| // Determine window start and end for current position | |
| let windowStart, windowEnd; | |
| if (threadId < WINDOW_SIZE) { | |
| // Growing window: out[0]=data[0], out[1]=data[0:1], out[2]=data[0:2] | |
| windowStart = 0; | |
| windowEnd = threadId + 1; | |
| } else { | |
| // Sliding window of size 3: out[3]=data[1:3], out[4]=data[2:4], etc. | |
| windowStart = threadId - WINDOW_SIZE + 1; | |
| windowEnd = threadId + 1; | |
| } | |
| // Highlight input window | |
| for (let i = windowStart; i < windowEnd; i++) { | |
| document.getElementById(`input-${i}`).classList.add('highlight'); | |
| } | |
| // Highlight memory window | |
| for (let i = windowStart; i < windowEnd; i++) { | |
| document.getElementById(`memory-${i}`).classList.add('window-highlight'); | |
| } | |
| // Calculate sum of elements in window | |
| let sum = 0; | |
| for (let i = windowStart; i < windowEnd; i++) { | |
| sum += inputData[i]; | |
| } | |
| // Highlight output | |
| const outputElement = document.getElementById(`output-${threadId}`); | |
| outputElement.classList.add('processing'); | |
| setTimeout(() => { | |
| outputElement.textContent = sum.toFixed(1); | |
| outputElement.classList.remove('processing'); | |
| outputElement.classList.add('highlight'); | |
| }, 400); | |
| } | |
| function stepAnimation() { | |
| if (currentStep < ARRAY_SIZE) { | |
| highlightWindow(currentStep); | |
| document.getElementById('current-step').textContent = currentStep + 1; | |
| currentStep++; | |
| } else { | |
| // Reset for next loop | |
| resetAnimation(); | |
| currentStep = 0; | |
| } | |
| } | |
| function startLoopingAnimation() { | |
| // Clear any existing interval | |
| if (animationInterval) { | |
| clearInterval(animationInterval); | |
| } | |
| // Start the looping animation | |
| animationInterval = setInterval(() => { | |
| stepAnimation(); | |
| }, 1200); | |
| } | |
| function resetAnimation() { | |
| document.getElementById('current-step').textContent = '0'; | |
| clearHighlights(); | |
| // Reset output array | |
| for (let i = 0; i < ARRAY_SIZE; i++) { | |
| document.getElementById(`output-${i}`).textContent = `out[${i}]`; | |
| } | |
| } | |
| // Initialize on page load | |
| window.addEventListener('load', initializeVisualization); | |
| </script> | |
| </body> | |
| </html> |