pin memory

This commit is contained in:
bluepulsar
2026-01-31 16:10:34 +08:00
parent 043f032f9d
commit d750a039fe
+34 -8
View File
@@ -243,21 +243,45 @@ class Tracker:
def setup_simple_raft(self):
"""
Setup a simpler version using available models
Setup a simpler version using available models with performance optimizations
"""
# Load model and move to GPU
model = raft_large(pretrained=True, progress=False).to(self.__raft_device)
model = model.eval()
# Optimize matmul precision for faster inference (TF32 on Ampere+ GPUs)
torch.set_float32_matmul_precision('medium')
# Enable CUDA-specific optimizations
if self.__raft_device == 'cuda':
# cuDNN optimizations
torch.backends.cudnn.benchmark = True # Auto-select fastest algorithms
torch.backends.cudnn.deterministic = False # Allow non-deterministic for speed
# TensorFloat-32 for Ampere+ GPUs (faster with minimal accuracy loss)
torch.backends.cuda.matmul.allow_tf32 = True
torch.backends.cudnn.allow_tf32 = True
print(f"RAFT model loaded on {self.__raft_device}")
return model
def _preprocess_frame_to_tensor(self, frame, resize=None):
"""Efficiently convert numpy frame to RAFT-ready tensor"""
# Upload to device as uint8 first to save bandwidth
# permute returns a view, but from_numpy usually shares memory.
# Moving to GPU as uint8 is fast.
tensor = torch.from_numpy(frame).permute(2, 0, 1).to(self.__raft_device)
# Ensure contiguous memory for faster tensor conversion
if not frame.flags['C_CONTIGUOUS']:
frame = np.ascontiguousarray(frame)
# Upload to device as uint8 first to save bandwidth (4x less data than float32)
tensor = torch.from_numpy(frame).permute(2, 0, 1)
# Move to device with non_blocking for async transfer (if CUDA)
# Pin memory for faster CPU-GPU transfer (similar to DataLoader pin_memory=True)
if self.__raft_device == 'cuda':
# Pin memory before transferring to GPU (must be on CPU first)
if not tensor.is_pinned():
tensor = tensor.pin_memory()
tensor = tensor.to(self.__raft_device, non_blocking=True)
else:
tensor = tensor.to(self.__raft_device)
# Convert to float and normalize on device
tensor = tensor.float() / 255.0
@@ -274,7 +298,7 @@ class Tracker:
# Keep in float32 - autocast will handle mixed precision during inference
return tensor
def track_raft(self, frame):
# No need to copy if we just read
# frame is expected to be (H, W, 3) or (H, W)
@@ -295,7 +319,8 @@ class Tracker:
prev_tensor = self.__raft_ref_tensor
curr_tensor = self._preprocess_frame_to_tensor(frame)
# Use autocast for automatic mixed precision (FP16 where supported, FP32 where needed)
# OPTIMIZATION: Remove CUDA stream since immediate sync eliminates async benefit
# The bottleneck is inference, not data transfer (already optimized with pin_memory)
with torch.no_grad():
if self.__raft_device == 'cuda':
with torch.amp.autocast('cuda'):
@@ -304,7 +329,8 @@ class Tracker:
flow = self.__raft_model(prev_tensor, curr_tensor)
predicted_flows = flow[-1]
flow_np = predicted_flows[0].float().cpu().numpy() # Convert back to float32 for numpy
# Optimize tensor->numpy conversion: contiguous() ensures optimal memory layout
flow_np = predicted_flows[0].contiguous().cpu().numpy()
# Transpose to (H, W, 2) format expected by draw_arrows
flow_np = flow_np.transpose(1, 2, 0) # (2, H, W) -> (H, W, 2)