Home/Data Structures & Algorithms/Bit Manipulation & Low-Level Computing

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.
SWAR bit counting, two’s complement invariants, bitmask permutations, hardware intrinsics, and Gray codes.
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.How to find the Single Number when all others appear 3 times using a Digital Logic State Machine?
This problem is a masterpiece of digital circuit design translated into software code. Let's design the state machine from first principles. 1. The Three States of a Bit For any bit position, as we scan numbers in the array, how many times can we see a 1? Seen 0 times → Count = 0 Seen 1 timeRead more
This problem is a masterpiece of digital circuit design translated into software code. Let’s design the state machine from first principles.
1. The Three States of a Bit
For any bit position, as we scan numbers in the array, how many times can we see a
1?To represent 3 distinct states (0, 1, and 2), we need 2 bits of memory! Let’s name them:
twos(the high bit)ones(the low bit)2. The Truth Table
When a new bit
xarrives from the current number:3. Deriving the Logic Gates
From the truth table:
ones = (ones ^ x) & (~twos)twos = (twos ^ x) & (~ones)When the full array has been scanned:
ones!Clean Python 3.12 Implementation
Complexity Breakdown
- Time Complexity:
- Space Complexity:
See lessO(N). We touch each number once with 4 single-cycle bitwise operations.O(1). Exactly two integer variables living in registers.How does Brian Kernighan’s bit algorithm work, and why does n & (n – 1) clear the lowest set bit?
The trick n & (n - 1) is one of the most elegant one-liners in computer engineering. Let's look at the exact bitwise mechanics so the mathematical proof becomes obvious. 1. What happens when you subtract 1 in binary? Think about standard base-10 math: when you subtract 1 from 1000, what happens?Read more
The trick
n & (n - 1)is one of the most elegant one-liners in computer engineering. Let’s look at the exact bitwise mechanics so the mathematical proof becomes obvious.1. What happens when you subtract 1 in binary?
Think about standard base-10 math: when you subtract 1 from
1000, what happens? The lowest non-zero digit (1) becomes 0, and all trailing zeroes become 9s:0999.Binary works exactly the same way, but with 0s and 1s:
Any positive binary integer can be written in this general form:
where the
1shown is the lowest set bit (the rightmost 1), followed by zero or more0s.When you compute
n - 1:1remains completely untouched.1turns into a0(borrowing from the subtraction).0s flip into1s!2. The Bitwise AND Operation: n & (n – 1)
Now perform a bitwise AND between
nandn - 1:Look at what happened:
prefixmatched identically → remains preserved.1was paired with0→ becomes0!0s were paired with1s → remain0!Conclusion: The operation
n & (n - 1)turns off the lowest set bit innand leaves every other bit completely unchanged. Pure mathematical magic!3. Real-World Applications
A. Counting Set Bits in O(k) time (where k is number of 1s)
Instead of looping 32 or 64 times, Brian Kernighan’s algorithm loops only as many times as there are 1-bits:
If a 64-bit integer has only two set bits, this loop executes exactly twice and terminates!
B. Instant Power of Two Check in O(1)
A power of two in binary has exactly one set bit (e.g.
8 = 1000_2,16 = 10000_2). If you strip that single bit and the result is 0, it was a power of 2:C. Hardware POPCNT Alternative
On modern x86_64 CPUs, you have the dedicated hardware assembly instruction
See lessPOPCNT(or__builtin_popcountin GCC/Clang), which computes set bits in a single CPU cycle. But when writing portable code or kernel routines without AVX/SSE guarantees, Brian Kernighan’s algorithm remains the golden standard.