
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
Join us in connecting knowledge with those who need it. Share your expertise, discover new perspectives, and help build a smarter, more connected world.
Create A New Account
pgvector: HNSW index build fails with out-of-memory or high swap: How to tune maintenance_work_mem & parallel workers
Direct Technical Solution: Unlike IVFFlat (which partitions vector spaces with k-means centroids), HNSW (Hierarchical Navigable Small World) constructs a multi-layer proximity graph in physical RAM during build time. For 2,000,000 vectors with 1,536 dimensions, the raw vectors alone occupy 2,000,000Read more
Direct Technical Solution: Unlike IVFFlat (which partitions vector spaces with k-means centroids), HNSW (Hierarchical Navigable Small World) constructs a multi-layer proximity graph in physical RAM during build time. For 2,000,000 vectors with 1,536 dimensions, the raw vectors alone occupy
2,000,000 × 1,536 × 4 bytes = 12.28 GB. Adding the HNSW graph neighbor connectivity lists (with m=16) increases total build RAM requirement to approximately 18 to 22 GB.1. The Formula to Calculate Required `maintenance_work_mem`
2. PostgreSQL Configuration Tuning
Temporarily allocate sufficient RAM to the session before triggering the index build, and utilize parallel CPU worker cores to accelerate graph edge exploration:
3. When to Use IVFFlat vs HNSW
Why does std::views::filter on temporary containers trigger undefined behavior and dangling references in C++20?
Direct Technical Solution: In C++20, range view adaptors (like std::views::filter, std::views::transform, and std::views::take) are strictly non-owning view wrappers. They do not duplicate or take ownership of the underlying container; they only store iterators pointing directly into the underlyingRead more
Direct Technical Solution: In C++20, range view adaptors (like
std::views::filter,std::views::transform, andstd::views::take) are strictly non-owning view wrappers. They do not duplicate or take ownership of the underlying container; they only store iterators pointing directly into the underlying sequence.In your code,
getTemperatures()returns a temporarystd::vector<int>by value. At the semicolon ending the initialization expressionauto warm_days = getTemperatures() | ...;, the temporary vector reaches the end of its full-expression lifetime and is immediately destructed. Consequently, the iterators stored insidewarm_daysbecome dangling pointers into deallocated stack/heap memory, causing undefined behavior upon iteration.PyTorch RuntimeError: CUDA out of memory: Why torch.cuda.empty_cache() fails & how to fix fragmentation
Direct Technical Solution: torch.cuda.empty_cache() releases only cached (unallocated) blocks back to the CUDA driver; it never frees memory occupied by active tensors (weights, optimizer states, computation graph nodes). Calling it inside your training loop hurts performance because CUDA must constRead more
Direct Technical Solution:
torch.cuda.empty_cache()releases only cached (unallocated) blocks back to the CUDA driver; it never frees memory occupied by active tensors (weights, optimizer states, computation graph nodes). Calling it inside your training loop hurts performance because CUDA must constantly re-allocate OS memory via costly system calls.1. Root Cause: PyTorch Allocator Memory Fragmentation
Look closely at your error message:
18.21 GiB allocated+4.80 GiB reserved. PyTorch had nearly 5 GB of memory held in its internal caching allocator, but it was split into scattered, non-contiguous memory chunks. When a tensor required 512 MiB of contiguous VRAM, the allocator failed to find a single chunk large enough.2. The Modern Fix: Expandable Segments (PyTorch 2.0+)
The definitive solution in modern PyTorch is activating virtual memory management via the
expandable_segmentsflag. This instructs CUDA to map physical memory pages to a contiguous virtual memory space, virtually eliminating memory fragmentation:3. The 4 Golden Rules to Prevent CUDA OOM
- Detach Loss Values: Never accumulate raw tensor losses:
- Use Automatic Mixed Precision (AMP): Halve activation memory using native BF16/FP16:
- Gradient Accumulation: Instead of a batch size of 64 that OOMs, use a micro-batch size of 16 and accumulate gradients across 4 backward steps:
- Zero Gradients with `set_to_none=True`:
See lesstotal_loss += lossretains the entire backward computation graph in VRAM! Always usetotal_loss += loss.item().optimizer.zero_grad(set_to_none=True)deallocates memory instead of zeroing tensors with zeros of equal size.Next.js 15: Error: Route used “params” without awaiting it (Asynchronous Page Props Fix)
Direct Technical Solution: In Next.js 15, dynamic route parameters (params) and search parameters (searchParams) transitioned from synchronous plain JavaScript objects to native Promises. This breaking change was implemented to support React 19 Server Components and the new Partial Prerendering (PPRRead more
Direct Technical Solution: In Next.js 15, dynamic route parameters (
params) and search parameters (searchParams) transitioned from synchronous plain JavaScript objects to native Promises. This breaking change was implemented to support React 19 Server Components and the new Partial Prerendering (PPR) model, where the server renders the static page skeleton before dynamic parameters resolve.1. Server Component Migration (Async/Await)
In all Next.js 15 Server Components (the default in the
app/directory), typeparamsas aPromiseand explicitlyawaitit before accessing any key:2. Client Component Migration (React 19 `use()` Hook)
If your page file uses
"use client", you cannot make the component functionasync. Instead, unwrap theparamsPromise using React 19’s nativeReact.use()hook:3. Comparison: Next.js 14 vs Next.js 15
{ slug: string }(Synchronous Object)Promise<{ slug: string }>(Async Promise)params.slug)const { slug } = await params;useParams()hookuse(params)oruseParams()Task Scheduler with Cooldowns: Closed-form mathematical formula vs Priority Queue simulation
The Task Scheduler problem is a masterclass in recognizing that the most frequent task dictates the entire schedule structure. 1. Deriving the Formula Visually Suppose our tasks are [A, A, A, B, B, C] with cooldown n = 2. Task A appears most frequently ($count = 3$). Between each A, there must be atRead more
The Task Scheduler problem is a masterclass in recognizing that the most frequent task dictates the entire schedule structure.
1. Deriving the Formula Visually
Suppose our tasks are
[A, A, A, B, B, C]with cooldownn = 2.Task
Aappears most frequently ($count = 3$). Between eachA, there must be at leastn = 2cooldown slots:Notice the structure:
max_freq - 1full frames.n + 1(the task itself plus itsncooldown slots).2. The Closed-Form Equation
Let
max_freqbe the highest frequency of any task, andmax_countbe how many tasks tie for that highest frequency (for example, if both A and B appear 3 times,max_count = 2).What if there are so many other tasks that no CPU idle slots are needed?
If you have tons of diverse tasks (e.g.
[A, A, B, B, C, D, E, F, G, H]), they easily fill up all idle slots, and the CPU never needs to idle at all! In that case, the answer is simplylen(tasks).Therefore, the global answer is simply:
Clean Python 3.12 Implementation (0 CPU Simulation Cycles!)
Complexity Breakdown
- Time Complexity:
- Space Complexity:
See lessO(N)to count task frequencies. The mathematical formula itself evaluates inO(1)time!O(1)auxiliary space, because the alphabet size is bounded by 26 English uppercase letters.Daily Temperatures: How to use an Index-Tracking Monotonic Stack for next warmer day in O(N)
This problem is the cleanest introductory template for the Monotonic Decreasing Stack pattern. Let's look at why storing indices unlocks the distance calculation. 1. The Mental Model Imagine people waiting in line holding temperature tickets. If temperatures are dropping: [73, 71, 69], nobody has foRead more
This problem is the cleanest introductory template for the Monotonic Decreasing Stack pattern. Let’s look at why storing indices unlocks the distance calculation.
1. The Mental Model
Imagine people waiting in line holding temperature tickets. If temperatures are dropping:
[73, 71, 69], nobody has found a warmer day yet! So everyone has to stay waiting in line.Now, a warm day arrives:
72!69sees72 > 69. Their wait is over! They step out of line.71sees72 > 71. Their wait is over! They step out of line.73sees72 < 73.72is not warm enough for them! The person with73stays waiting in line, and the day with72joins the line behind them.2. Why Store Indices Instead of Values?
If you only push temperature numbers (e.g.
69) onto the stack, when a warmer day72pops69, you know that a warmer day happened, but you don’t know how many days elapsed!By pushing the array index
prev_dayonto the stack:You calculate the exact time difference in $O(1)$ and write directly to the output array!
Clean Python 3.12 Implementation
Complexity Breakdown
- Time Complexity:
- Space Complexity:
See lessO(N). Every index is pushed onto the stack once and popped at most once. Total operations: $le 2N$.O(N)for the stack in the worst-case of strictly decreasing temperatures (e.g.[100, 90, 80, 70]).Lowest Common Ancestor: Why Binary Lifting in O(log N) beats naive DFS in high-scale DAGs
When you have multiple online LCA queries on a static tree, the gold standard is Binary Lifting (used in compiler dominance frontiers, distributed network routing, and Git commit histories). 1. The Core Idea: Powers of 2 Parent Jumps Instead of storing only a node's immediate parent (which forces yoRead more
When you have multiple online LCA queries on a static tree, the gold standard is Binary Lifting (used in compiler dominance frontiers, distributed network routing, and Git commit histories).
1. The Core Idea: Powers of 2 Parent Jumps
Instead of storing only a node’s immediate parent (which forces you to step up the tree one node at a time in $O(N)$), what if every node stored its ancestor at distance $2^0, 2^1, 2^2, 2^3, dots, 2^k$?
We define a 2D table:
up[u][i] = the (2^i)-th ancestor of node u.The state transition is pure dynamic programming:
In English: ‘To jump $2^i$ steps up from $u$, first jump $2^{i-1}$ steps up to reach intermediate node $v$, and then from $v$ jump another $2^{i-1}$ steps!’ ($2^{i-1} + 2^{i-1} = 2^i$).
2. Answering an LCA Query in 2 Steps
To find the LCA of nodes
uandv:depth[u] < depth[v], swap them. Use binary powers to jumpuupwards untildepth[u] == depth[v]in $O(log N)$ steps. Ifu == v, they were on the same branch → returnu!uandvupwards together using the largest possible power of 2 such that their ancestors are still different (up[u][i] != up[v][i]). When no more jumps can be made, their immediate parent (up[u][0]) is their Lowest Common Ancestor!Clean C++20 Implementation
Complexity Breakdown
- Preprocessing Time:
- Preprocessing Memory:
- Per Query Time: Strictly
See lessO(N log N)via a single DFS pass.O(N log N)to store the jump table.O(log N). For $N = 1,000,000$, $log_2(1,000,000) pprox 20$ operations. You can evaluate 50,000 queries in a fraction of a second!