wip(standalone): GPU step 21 -- GPU input export shares the 8 workers (3:1 priority); no wall gain

Export tasks interleave with CPU tile jobs on the existing pool. Slow-dispatch keys
are logged (>5 ms, with -Timeline).
My runs outside the sandbox (Step21.exe, marker removed first, interleaved, GPU with
-Timeline):
  CPU 1.356 / 1.321 / 1.277 s
  GPU 1.453 (marker miss, 0 GPU tiles) / 1.249 / 1.216 / 1.217 s (match)
Export now starts at 686 ms in run c (was ~850), but the whole view is unchanged
(1.216 s): from first input (721 ms) to ready (1,216 ms) the GPU path spends ~500 ms
wall for ~255 ms of GPU timestamps. In runs b/d the output pool itself began late
(~860-875 ms). Slow tiles: (0,-6,-5,lod1) 28.5 ms, (-4,-15,-3,lod0) 11.3 ms,
(-3,-13,-2,lod0) 8.2 ms, all ordinary near-detail tiles.
Audits: hashes w1/w8, walk 5,642/5,642, near 960 / far 1,114 0 diffs vs CPU and
WARP, thin 353, survival 6.13 GiB, ten captures as step 18.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-07 23:20:42 +02:00
1 parent 2cb3344e1b
commit 38f6009200
5 files changed
+308 -119

No files matched your search

+45 -5
View File
@@ -11,8 +11,11 @@
#include <chrono>
#include <cstdint>
#include <cstring>
#include <deque>
#include <functional>
#include <fstream>
#include <unordered_set>
#include <utility>
struct FStandaloneTileKeyHash
{
@@ -467,12 +470,30 @@ public:
bUseTileFilter=true;
}
bool QueuePriorityTasks(std::vector<std::function<void()>> Tasks)
{
if(Tasks.empty())return true;
{
std::lock_guard<std::mutex> Lock(Mutex);
if(bStop||Workers.empty())return false;
for(auto& Task:Tasks)PriorityTasks.push_back(std::move(Task));
}
Wake.notify_all();
return true;
}
void ClearPriorityTasks()
{
std::lock_guard<std::mutex> Lock(Mutex);
PriorityTasks.clear();
}
void Stop()
{
{
std::lock_guard<std::mutex> Lock(Mutex);
bStop=true;
Queue.clear();
Queue.clear();PriorityTasks.clear();
}
Wake.notify_all();
for(std::thread& Worker:Workers)if(Worker.joinable())Worker.join();
@@ -799,16 +820,34 @@ private:
void WorkerLoop()
{
constexpr uint32 PriorityTaskBurst=3;
uint32 ConsecutivePriorityTasks=0;
for(;;)
{
FStandaloneTileJob Job;
std::function<void()> PriorityTask;
{
std::unique_lock<std::mutex> Lock(Mutex);
Wake.wait(Lock,[&](){return bStop||!Queue.empty();});
Wake.wait(Lock,[&](){return bStop||!PriorityTasks.empty()||!Queue.empty();});
if(bStop)return;
std::pop_heap(Queue.begin(),Queue.end(),FStandaloneTileJobHeapOrder{});
Job=Queue.back();Queue.pop_back();Job.StartedAt=FClock::now();
Running.insert(Job.Key);
const bool bPreferPriority=!PriorityTasks.empty()
&&(Queue.empty()||ConsecutivePriorityTasks<PriorityTaskBurst);
if(bPreferPriority)
{
PriorityTask=std::move(PriorityTasks.front());PriorityTasks.pop_front();
++ConsecutivePriorityTasks;
}
else
{
std::pop_heap(Queue.begin(),Queue.end(),FStandaloneTileJobHeapOrder{});
Job=Queue.back();Queue.pop_back();Job.StartedAt=FClock::now();
Running.insert(Job.Key);ConsecutivePriorityTasks=0;
}
}
if(PriorityTask)
{
PriorityTask();
continue;
}
if(bColdTimelineTrace)TraceTileEvent("started",Job.Key,Job.StartedAt,Job.QueuedAt,Job.StartedAt);
FStandaloneCpuTile Tile=Generate(Job);
@@ -857,6 +896,7 @@ private:
std::condition_variable Wake;
bool bStop=true;
std::vector<std::thread> Workers;
std::deque<std::function<void()>> PriorityTasks;
std::vector<FStandaloneTileJob> Queue;
std::vector<FStandaloneCpuTile> Ready;
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> Running;