feat: use both GPUs in parallel for streaming quantization

This commit is contained in:
Christian Medina
2026-07-02 21:30:35 -04:00
parent 0ea51488a7
commit aec7f405fe

View File

@@ -11,7 +11,7 @@ from torch import nn
def streaming_quantize(model_path, output_path): def streaming_quantize(model_path, output_path):
"""Quantize model by processing one shard at a time.""" """Quantize model by processing one shard at a time, using both GPUs."""
print(f"Loading config from: {model_path}") print(f"Loading config from: {model_path}")
config = AutoConfig.from_pretrained(model_path, trust_remote_code=True) config = AutoConfig.from_pretrained(model_path, trust_remote_code=True)
@@ -35,13 +35,21 @@ def streaming_quantize(model_path, output_path):
print(" Loading shard to CPU...") print(" Loading shard to CPU...")
shard_state_dict = torch.load(shard_file, map_location="cpu", weights_only=True) shard_state_dict = torch.load(shard_file, map_location="cpu", weights_only=True)
# Quantize Linear layers in this shard # Quantize Linear layers in this shard using both GPUs
print(" Quantizing Linear layers...") print(" Quantizing Linear layers (both GPUs)...")
quantized_keys = 0 quantized_keys = 0
for key, tensor in list(shard_state_dict.items()):
if 'weight' in key and tensor.dim() == 2: # Get all weight tensors
# This is a Linear layer weight weight_keys = [k for k, v in shard_state_dict.items() if 'weight' in k and v.dim() == 2]
# Create a dummy Linear4bit to get the quantization format
# Distribute between GPUs
gpu0_keys = weight_keys[::2] # Even indices
gpu1_keys = weight_keys[1::2] # Odd indices
# Quantize on GPU 0
print(" GPU 0: Quantizing...", end=" ")
for key in gpu0_keys:
tensor = shard_state_dict[key]
in_features = tensor.size(1) in_features = tensor.size(1)
out_features = tensor.size(0) out_features = tensor.size(0)
@@ -53,17 +61,38 @@ def streaming_quantize(model_path, output_path):
quant_type='nf4', quant_type='nf4',
) )
# Quantize the weight
with torch.no_grad(): with torch.no_grad():
dummy_linear.weight = nn.Parameter(tensor.clone()) dummy_linear.weight = nn.Parameter(tensor.clone().to("cuda:0"))
# Force quantization by accessing quant_state
_ = dummy_linear.weight.quant_state _ = dummy_linear.weight.quant_state
# Replace with quantized version shard_state_dict[key] = dummy_linear.weight.to("cpu")
shard_state_dict[key] = dummy_linear.weight
quantized_keys += 1 quantized_keys += 1
print(f"{len(gpu0_keys)} layers")
print(f" ✓ Quantized {quantized_keys} weights") # Quantize on GPU 1
print(" GPU 1: Quantizing...", end=" ")
for key in gpu1_keys:
tensor = shard_state_dict[key]
in_features = tensor.size(1)
out_features = tensor.size(0)
dummy_linear = Linear4bit(
in_features,
out_features,
bias=False,
compute_dtype=torch.float16,
quant_type='nf4',
)
with torch.no_grad():
dummy_linear.weight = nn.Parameter(tensor.clone().to("cuda:1"))
_ = dummy_linear.weight.quant_state
shard_state_dict[key] = dummy_linear.weight.to("cpu")
quantized_keys += 1
print(f"{len(gpu1_keys)} layers")
print(f" ✓ Total: {quantized_keys} layers quantized")
# Save quantized shard # Save quantized shard
shard_name = f"model_shard_{shard_idx:05d}.safetensors" shard_name = f"model_shard_{shard_idx:05d}.safetensors"
@@ -74,6 +103,7 @@ def streaming_quantize(model_path, output_path):
# Free memory # Free memory
del shard_state_dict del shard_state_dict
gc.collect() gc.collect()
torch.cuda.empty_cache()
# Save config # Save config
print(f"\n{'='*60}") print(f"\n{'='*60}")
@@ -86,6 +116,7 @@ def streaming_quantize(model_path, output_path):
torch.cuda.empty_cache() torch.cuda.empty_cache()
print("\n✓ Streaming quantization complete!") print("\n✓ Streaming quantization complete!")
print(f" Used both GPUs in parallel for faster quantization")
def main(): def main():