279 lines
8.7 KiB
HTML
279 lines
8.7 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="en">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>Render Farm Throughput Calculator • stream.4ort.net</title>
|
|||
|
|
<style>
|
|||
|
|
:root { --bg: #050505; --fg: #e0e0e0; --accent: #7aa2f7; --border: #1a1a1a; --muted: #666; }
|
|||
|
|
* { box-sizing: border-box; }
|
|||
|
|
body {
|
|||
|
|
background: var(--bg);
|
|||
|
|
color: var(--fg);
|
|||
|
|
font-family: system-ui, -apple-system, sans-serif;
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 3rem;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
}
|
|||
|
|
.container { max-width: 980px; margin: 0 auto; }
|
|||
|
|
header {
|
|||
|
|
border-left: 3px solid var(--accent);
|
|||
|
|
padding-left: 2rem;
|
|||
|
|
margin-bottom: 3rem;
|
|||
|
|
}
|
|||
|
|
h1 {
|
|||
|
|
font-size: 2.8rem;
|
|||
|
|
letter-spacing: -0.05em;
|
|||
|
|
margin: 0 0 0.5rem 0;
|
|||
|
|
line-height: 1.1;
|
|||
|
|
}
|
|||
|
|
.subtitle {
|
|||
|
|
font-size: 1rem;
|
|||
|
|
opacity: 0.7;
|
|||
|
|
margin-bottom: 1rem;
|
|||
|
|
font-family: monospace;
|
|||
|
|
}
|
|||
|
|
.tool-section {
|
|||
|
|
background: rgba(26, 26, 26, 0.3);
|
|||
|
|
border: 1px solid var(--border);
|
|||
|
|
padding: 2rem;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
margin: 2rem 0;
|
|||
|
|
}
|
|||
|
|
.input-group {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 200px 1fr;
|
|||
|
|
gap: 1rem;
|
|||
|
|
align-items: baseline;
|
|||
|
|
margin-bottom: 1rem;
|
|||
|
|
}
|
|||
|
|
label {
|
|||
|
|
font-family: monospace;
|
|||
|
|
font-size: 0.9rem;
|
|||
|
|
opacity: 0.8;
|
|||
|
|
}
|
|||
|
|
input[type="number"] {
|
|||
|
|
background: var(--bg);
|
|||
|
|
border: 1px solid var(--border);
|
|||
|
|
color: var(--fg);
|
|||
|
|
padding: 0.5rem 1rem;
|
|||
|
|
font-family: monospace;
|
|||
|
|
font-size: 1rem;
|
|||
|
|
width: 100%;
|
|||
|
|
border-radius: 2px;
|
|||
|
|
}
|
|||
|
|
input[type="number"]:focus {
|
|||
|
|
outline: none;
|
|||
|
|
border-color: var(--accent);
|
|||
|
|
}
|
|||
|
|
button {
|
|||
|
|
background: var(--accent);
|
|||
|
|
color: var(--bg);
|
|||
|
|
border: none;
|
|||
|
|
padding: 0.75rem 2rem;
|
|||
|
|
font-family: monospace;
|
|||
|
|
font-size: 1rem;
|
|||
|
|
font-weight: bold;
|
|||
|
|
cursor: pointer;
|
|||
|
|
border-radius: 2px;
|
|||
|
|
transition: all 0.15s ease;
|
|||
|
|
}
|
|||
|
|
button:hover {
|
|||
|
|
transform: translateY(-2px);
|
|||
|
|
box-shadow: 0 4px 12px rgba(122, 162, 247, 0.3);
|
|||
|
|
}
|
|||
|
|
.results {
|
|||
|
|
margin-top: 2rem;
|
|||
|
|
padding-top: 2rem;
|
|||
|
|
border-top: 1px solid var(--border);
|
|||
|
|
}
|
|||
|
|
.result-row {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
padding: 0.75rem 0;
|
|||
|
|
border-bottom: 1px dashed var(--border);
|
|||
|
|
font-family: monospace;
|
|||
|
|
}
|
|||
|
|
.result-row:last-child { border-bottom: none; }
|
|||
|
|
.result-label { opacity: 0.7; }
|
|||
|
|
.result-value { font-weight: bold; color: var(--accent); }
|
|||
|
|
.formula-box {
|
|||
|
|
background: rgba(122, 162, 247, 0.05);
|
|||
|
|
border: 1px solid var(--accent);
|
|||
|
|
padding: 1.5rem;
|
|||
|
|
margin: 2rem 0;
|
|||
|
|
font-family: monospace;
|
|||
|
|
font-size: 0.9rem;
|
|||
|
|
}
|
|||
|
|
.formula-box h3 {
|
|||
|
|
margin-top: 0;
|
|||
|
|
color: var(--accent);
|
|||
|
|
font-size: 1rem;
|
|||
|
|
margin-bottom: 1rem;
|
|||
|
|
}
|
|||
|
|
.citation {
|
|||
|
|
font-size: 0.75rem;
|
|||
|
|
opacity: 0.5;
|
|||
|
|
margin-top: 1rem;
|
|||
|
|
font-family: monospace;
|
|||
|
|
}
|
|||
|
|
nav.nav {
|
|||
|
|
margin-top: 3rem;
|
|||
|
|
padding-top: 2rem;
|
|||
|
|
border-top: 1px solid var(--border);
|
|||
|
|
font-size: 0.85rem;
|
|||
|
|
opacity: 0.6;
|
|||
|
|
}
|
|||
|
|
nav.nav a {
|
|||
|
|
color: var(--accent);
|
|||
|
|
text-decoration: none;
|
|||
|
|
margin-right: 1.5rem;
|
|||
|
|
}
|
|||
|
|
.error {
|
|||
|
|
color: #ff6b6b;
|
|||
|
|
font-family: monospace;
|
|||
|
|
font-size: 0.85rem;
|
|||
|
|
margin-top: 1rem;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="container">
|
|||
|
|
<header>
|
|||
|
|
<h1>RENDER FARM THROUGHPUT CALCULATOR</h1>
|
|||
|
|
<div class="subtitle">Q382597 // Q7798498 — COMPUTE CAPACITY PLANNING ENGINE</div>
|
|||
|
|
<p>Compute total frames rendered per hour given node count, GPU throughput, and scene complexity. Grounded in Wikidata definitions of render farm architecture and throughput rate.</p>
|
|||
|
|
</header>
|
|||
|
|
|
|||
|
|
<div class="formula-box">
|
|||
|
|
<h3>CORE FORMULA</h3>
|
|||
|
|
<p><strong>T = N × (F ÷ S) × 3600</strong></p>
|
|||
|
|
<p style="margin-top: 1rem; opacity: 0.8;">Where:<br>
|
|||
|
|
T = Total frames per hour<br>
|
|||
|
|
N = Number of nodes in cluster<br>
|
|||
|
|
F = Frames per second per GPU (base throughput)<br>
|
|||
|
|
S = Scene complexity factor (1.0 = reference scene)<br>
|
|||
|
|
3600 = Seconds per hour</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="tool-section">
|
|||
|
|
<h3 style="color: var(--accent); margin-top: 0;">INPUT PARAMETERS</h3>
|
|||
|
|
|
|||
|
|
<div class="input-group">
|
|||
|
|
<label for="nodes">NODE COUNT (N)</label>
|
|||
|
|
<input type="number" id="nodes" placeholder="e.g., 64" min="1" step="1">
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="input-group">
|
|||
|
|
<label for="fps_per_gpu">FPS PER GPU (F)</label>
|
|||
|
|
<input type="number" id="fps_per_gpu" placeholder="e.g., 24" min="0.1" step="0.1">
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="input-group">
|
|||
|
|
<label for="complexity">SCENE FACTOR (S)</label>
|
|||
|
|
<input type="number" id="complexity" placeholder="e.g., 2.5" min="0.1" step="0.1" value="1.0">
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<button onclick="calculateThroughput()">COMPUTE THROUGHPUT</button>
|
|||
|
|
|
|||
|
|
<div id="error-msg" class="error"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="results" id="results" style="display: none;">
|
|||
|
|
<h3 style="color: var(--accent);">CALCULATED OUTPUT</h3>
|
|||
|
|
|
|||
|
|
<div class="result-row">
|
|||
|
|
<span class="result-label">FRAMES PER HOUR</span>
|
|||
|
|
<span class="result-value" id="frames-per-hour">-</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="result-row">
|
|||
|
|
<span class="result-label">SECONDS PER FRAME</span>
|
|||
|
|
<span class="result-value" id="seconds-per-frame">-</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="result-row">
|
|||
|
|
<span class="result-label">MINUTES PER FRAME</span>
|
|||
|
|
<span class="result-value" id="minutes-per-frame">-</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="result-row">
|
|||
|
|
<span class="result-label">HOURLY THROUGHPUT (T⁻¹)</span>
|
|||
|
|
<span class="result-value" id="hourly-rate">-</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="result-row">
|
|||
|
|
<span class="result-label">EST. RENDER TIME FOR 1-HOUR SEQUENCE</span>
|
|||
|
|
<span class="result-value" id="sequence-time">-</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="citation">
|
|||
|
|
SOURCE: Wikidata Q382597 (render_farm), Q7798498 (throughput) — CC0<br>
|
|||
|
|
DATA: render-farm-calculator.json | ARCHITECTURE: render-farm-architecture.html | SPEC: render-farm-spec.html
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<nav class="nav">
|
|||
|
|
<a href="index.html">INDEX</a>
|
|||
|
|
<a href="render-farm-architecture.html">ARCHITECTURE</a>
|
|||
|
|
<a href="render-farm-spec.html">SPECIFICATION</a>
|
|||
|
|
<a href="throughput-q7798498.html">THROUGHPUT</a>
|
|||
|
|
<a href="recovery-protocol.html">RECOVERY</a>
|
|||
|
|
</nav>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
function calculateThroughput() {
|
|||
|
|
const errorMsg = document.getElementById('error-msg');
|
|||
|
|
const resultsDiv = document.getElementById('results');
|
|||
|
|
|
|||
|
|
errorMsg.textContent = '';
|
|||
|
|
resultsDiv.style.display = 'none';
|
|||
|
|
|
|||
|
|
const N = parseFloat(document.getElementById('nodes').value);
|
|||
|
|
const F = parseFloat(document.getElementById('fps_per_gpu').value);
|
|||
|
|
const S = parseFloat(document.getElementById('complexity').value);
|
|||
|
|
|
|||
|
|
if (!N || N <= 0) {
|
|||
|
|
errorMsg.textContent = 'ERROR: Node count must be positive integer.';
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!F || F <= 0) {
|
|||
|
|
errorMsg.textContent = 'ERROR: FPS per GPU must be positive.';
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (!S || S <= 0) {
|
|||
|
|
errorMsg.textContent = 'ERROR: Scene complexity factor must be positive.';
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Core calculation: T = N × (F ÷ S) × 3600
|
|||
|
|
const effectiveFPSPerNode = F / S;
|
|||
|
|
const totalFPS = N * effectiveFPSPerNode;
|
|||
|
|
const framesPerHour = totalFPS * 3600;
|
|||
|
|
|
|||
|
|
// Time per frame in seconds
|
|||
|
|
const secondsPerFrame = S / F;
|
|||
|
|
const minutesPerFrame = secondsPerFrame / 60;
|
|||
|
|
|
|||
|
|
// Hourly throughput rate (T⁻¹ dimension)
|
|||
|
|
const hourlyRate = framesPerHour;
|
|||
|
|
|
|||
|
|
// Estimate for 1-hour sequence (assuming 24fps output = 86400 frames)
|
|||
|
|
const sequenceFrames = 86400; // 24 fps × 3600 seconds
|
|||
|
|
const sequenceHours = sequenceFrames / framesPerHour;
|
|||
|
|
const sequenceMinutes = sequenceHours * 60;
|
|||
|
|
|
|||
|
|
document.getElementById('frames-per-hour').textContent = framesPerHour.toPrecision(6) + ' fr/hr';
|
|||
|
|
document.getElementById('seconds-per-frame').textContent = secondsPerFrame.toFixed(4) + ' s';
|
|||
|
|
document.getElementById('minutes-per-frame').textContent = minutesPerFrame.toFixed(6) + ' min';
|
|||
|
|
document.getElementById('hourly-rate').textContent = hourlyRate.toPrecision(6) + ' T⁻¹';
|
|||
|
|
document.getElementById('sequence-time').textContent = `${sequenceHours.toFixed(2)} hr (${sequenceMinutes.toFixed(1)} min)`;
|
|||
|
|
|
|||
|
|
resultsDiv.style.display = 'block';
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|