wip(assembler): round S14 -- 4-way column cache + memoized MC gradients (output unchanged)
Worker-local XY column cache uses deterministic 4-way sets at LOD3-8: LOD4 misses 8,224 -> 1,437, conflicts 7,407 -> 0 (direct-map control: 6.62 s / 43.5 worker-s vs 4.24 s / 21.7). Exact LOD0 lattice gradients memoized per tile: MC-exclusive 242 -> 201 ns/sample, two-pass loop unchanged. Hashes identical, no recipe bump. Primary cold trace 4.24 s full set, ring 0.45 s, 75/75 at 40 m/s; a repeat ran uniformly ~40% slower on every LOD (machine contention suspected); tick p95 to re-check on an idle machine. CVars voxel.CoreColumnCacheDirectMapped / voxel.CoreMCGradientMemoization. Report: Standalone/Research/WorldAssemblerM3/Round18. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
bd5e38594f
commit
ec2afe9c93
11 files changed
+769
-50
No files matched your search
@@ -1361,11 +1361,35 @@ namespace world_assembly_detail
|
||||
std::int64_t x = 0, y = 0;
|
||||
HeightfieldPointSample column{};
|
||||
};
|
||||
// Coarse LOD tiles revisit a wider set of gradient-sample columns than the full-resolution
|
||||
// band. Keep those columns resident for a complete worker tile so the 3D mesher does not
|
||||
// repeat the procedural biome evaluation for every Z sample.
|
||||
// Keep 65,536 entries in each worker cache; four ways tolerate coordinate families that
|
||||
// deliberately share low hash bits at coarse LODs.
|
||||
// Chaque cache worker garde 65 536 entrees; quatre voies absorbent les coordonnees grossieres
|
||||
// qui partagent les bits faibles du hash.
|
||||
constexpr std::size_t HeightfieldColumnCacheWays=4;
|
||||
constexpr std::size_t HeightfieldColumnCacheSetCount=65536/HeightfieldColumnCacheWays;
|
||||
inline thread_local std::array<HeightfieldColumnCacheEntry, 65536> HeightfieldColumnCache{};
|
||||
inline thread_local std::array<std::uint8_t, HeightfieldColumnCacheSetCount>
|
||||
HeightfieldColumnCacheNextWay{};
|
||||
inline thread_local HeightfieldColumnCacheStats HeightfieldColumnStats{};
|
||||
inline thread_local bool HeightfieldColumnCacheLegacyDirectMapped=false;
|
||||
|
||||
inline std::size_t HeightfieldColumnCacheSet(const WorldAssemblyRecipeV1& recipe,
|
||||
const WorldAssemblyStratumPlanV1& plan,std::int64_t x,std::int64_t y) noexcept
|
||||
{
|
||||
// Avalanche every coordinate bit before masking. The old direct hash kept too little
|
||||
// entropy from widely spaced coarse LOD coordinates in its low 16 bits.
|
||||
// Melanger tous les bits de coordonnee avant le masque; l'ancien hash perdait de
|
||||
// l'entropie sur les coordonnees espacees des LOD grossiers.
|
||||
std::uint64_t mixed=static_cast<std::uint64_t>(x)*0x9E3779B185EBCA87ull
|
||||
^std::rotl(static_cast<std::uint64_t>(y)*0xC2B2AE3D27D4EB4Full,29)
|
||||
^recipe.contentHash^std::rotl(plan.contentHash,17);
|
||||
mixed^=mixed>>30;
|
||||
mixed*=0xBF58476D1CE4E5B9ull;
|
||||
mixed^=mixed>>27;
|
||||
mixed*=0x94D049BB133111EBull;
|
||||
mixed^=mixed>>31;
|
||||
return static_cast<std::size_t>(mixed)&(HeightfieldColumnCacheSetCount-1);
|
||||
}
|
||||
|
||||
inline HeightfieldPointSample EvaluateColumn(const WorldAssemblyRecipeV1& recipe,
|
||||
const WorldAssemblyStratumPlanV1& plan,std::int64_t x,std::int64_t y)
|
||||
@@ -1480,15 +1504,48 @@ namespace world_assembly_detail
|
||||
inline HeightfieldPointSample CachedColumn(const WorldAssemblyRecipeV1& recipe,
|
||||
const WorldAssemblyStratumPlanV1& plan,std::int64_t x,std::int64_t y)
|
||||
{
|
||||
const std::uint64_t mixed=(static_cast<std::uint64_t>(x)*0x9E3779B185EBCA87ull)
|
||||
^std::rotl(static_cast<std::uint64_t>(y)*0xC2B2AE3D27D4EB4Full,23)
|
||||
^static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(&recipe))
|
||||
^std::rotl(static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(&plan)),41);
|
||||
auto& entry=HeightfieldColumnCache[static_cast<std::size_t>(mixed)&
|
||||
(HeightfieldColumnCache.size()-1)];
|
||||
if(entry.recipe==&recipe&&entry.plan==&plan&&entry.recipeHash==recipe.contentHash
|
||||
&&entry.planHash==plan.contentHash&&entry.x==x&&entry.y==y)
|
||||
{++HeightfieldColumnStats.columnHits;return entry.column;}
|
||||
HeightfieldColumnCacheEntry* replacement=nullptr;
|
||||
if(HeightfieldColumnCacheLegacyDirectMapped)
|
||||
{
|
||||
// Preserve S13's exact direct-map index as an in-process negative control.
|
||||
// Conserver l'index direct exact de S13 comme controle negatif en cours d'execution.
|
||||
const std::uint64_t mixed=(static_cast<std::uint64_t>(x)*0x9E3779B185EBCA87ull)
|
||||
^std::rotl(static_cast<std::uint64_t>(y)*0xC2B2AE3D27D4EB4Full,23)
|
||||
^static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(&recipe))
|
||||
^std::rotl(static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(&plan)),41);
|
||||
replacement=&HeightfieldColumnCache[static_cast<std::size_t>(mixed)
|
||||
&(HeightfieldColumnCache.size()-1)];
|
||||
if(replacement->recipe==&recipe&&replacement->plan==&plan
|
||||
&&replacement->recipeHash==recipe.contentHash
|
||||
&&replacement->planHash==plan.contentHash&&replacement->x==x&&replacement->y==y)
|
||||
{++HeightfieldColumnStats.columnHits;return replacement->column;}
|
||||
if(replacement->recipe!=nullptr)++HeightfieldColumnStats.columnConflictMisses;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::size_t set=HeightfieldColumnCacheSet(recipe,plan,x,y);
|
||||
const std::size_t first=set*HeightfieldColumnCacheWays;
|
||||
std::size_t replacementWay=HeightfieldColumnCacheWays;
|
||||
for(std::size_t way=0;way<HeightfieldColumnCacheWays;++way)
|
||||
{
|
||||
auto& candidate=HeightfieldColumnCache[first+way];
|
||||
if(candidate.recipe==&recipe&&candidate.plan==&plan
|
||||
&&candidate.recipeHash==recipe.contentHash&&candidate.planHash==plan.contentHash
|
||||
&&candidate.x==x&&candidate.y==y)
|
||||
{++HeightfieldColumnStats.columnHits;return candidate.column;}
|
||||
if(candidate.recipe==nullptr&&replacementWay==HeightfieldColumnCacheWays)
|
||||
replacementWay=way;
|
||||
}
|
||||
if(replacementWay==HeightfieldColumnCacheWays)
|
||||
{
|
||||
++HeightfieldColumnStats.columnConflictMisses;
|
||||
replacementWay=HeightfieldColumnCacheNextWay[set];
|
||||
}
|
||||
HeightfieldColumnCacheNextWay[set]=static_cast<std::uint8_t>(
|
||||
(replacementWay+1)%HeightfieldColumnCacheWays);
|
||||
replacement=&HeightfieldColumnCache[first+replacementWay];
|
||||
}
|
||||
auto& entry=*replacement;
|
||||
const auto start=std::chrono::steady_clock::now();
|
||||
HeightfieldPointSample column=EvaluateColumn(recipe,plan,x,y);
|
||||
HeightfieldColumnStats.columnComputeMilliseconds+=std::chrono::duration<double,std::milli>(
|
||||
@@ -1977,19 +2034,27 @@ void Heightfield2D::resetThreadColumnCacheStats(bool captureCoordinates, bool cl
|
||||
{
|
||||
// Diagnostic probes may clear old tile entries before comparing isolated sample grids.
|
||||
// Les sondes de mesure peuvent vider les entrees d'une tuile avant de comparer deux grilles.
|
||||
if(clearCache)world_assembly_detail::HeightfieldColumnCache.fill(
|
||||
world_assembly_detail::HeightfieldColumnCacheEntry{});
|
||||
if(clearCache)
|
||||
{
|
||||
world_assembly_detail::HeightfieldColumnCache.fill(
|
||||
world_assembly_detail::HeightfieldColumnCacheEntry{});
|
||||
world_assembly_detail::HeightfieldColumnCacheNextWay.fill(0);
|
||||
}
|
||||
auto& Stats=world_assembly_detail::HeightfieldColumnStats;
|
||||
world_assembly_detail::HeightfieldColumnOctaveDrop=octaveDrop;
|
||||
Stats.pointCalls=0;
|
||||
Stats.columnHits=0;
|
||||
Stats.columnMisses=0;
|
||||
Stats.columnConflictMisses=0;
|
||||
Stats.columnComputeMilliseconds=0.0;
|
||||
Stats.captureCoordinates=captureCoordinates;
|
||||
Stats.coordinateCaptureComplete=true;
|
||||
Stats.evaluatedCoordinates.clear();
|
||||
}
|
||||
|
||||
void Heightfield2D::setThreadColumnCacheLegacyDirectMapped(bool enabled) noexcept
|
||||
{ world_assembly_detail::HeightfieldColumnCacheLegacyDirectMapped=enabled; }
|
||||
|
||||
const HeightfieldColumnCacheStats& Heightfield2D::threadColumnCacheStats() noexcept
|
||||
{ return world_assembly_detail::HeightfieldColumnStats; }
|
||||
|
||||
|
||||
Reference in new issue
Block a user