bitscom is a low-bit distributed communication library for PyTorch. It provides:
- A custom
torch.distributedbackend namedlowbit - A Python wrapper API
LowBitGroup - A Python fallback quantization/bit-packing module for development and tests
Core objective:
- Reduce communication traffic in distributed training by sending quantized low-bit representations instead of full-precision tensors.
Current architecture:
- C++ backend (
ProcessGroupLowBit) wraps NCCL process group calls. - Python API (
bitscom.LowBitGroup) exposes collective operations. - Python quantization module (
bitscom.quantization) provides functional compression/decompression logic that can be tested without GPUs.
- Supported quantization bitwidths:
1, 2, 4, 8, 12, 16 - Tensor quantize/dequantize utilities
- Bit-packing and unpacking for the supported bitwidths
- CUDA quantization/pack/unpack fast path for
1/2/4/8bit - Stochastic rounding support in quantization (CPU + CUDA)
LowBitGroup.compress()andLowBitGroup.decompress()helper APIs- Optional simulation mode (
simulate_quantization=True) for validating quantization effect before collectives - Blockwise quantization with per-block FP16 scales for low-bit all-reduce
- Python low-bit all-reduce pipeline for
<8bit(all-to-all -> local reduce -> all-gather) - Hierarchical pipeline-A low-bit all-reduce (
local reduce -> inter lowbit all-reduce -> local broadcast) - Multi-node CUDA dual-stream scheduling for pipeline-A (
warmup -> steady -> cooldown) - Single-node local-group-only fast path: one-shot full-precision all-reduce without chunked pipeline
- Error-feedback in first-stage quantization for C++ backend low-bit allreduce path
- Explicit backend option registration:
bitwidth,error_feedback,block_size,stage2_error_feedback - Robust backend registration with explicit error when C++ extension is missing
- Build-time
compile_commands.jsonemission for clangd
The following items are still pending and marked as future work:
- In-backend low-bit paths for
allgatherandreduce_scatter(currently forwarded to NCCL) - End-to-end multi-node benchmark suite and scaling analysis
- Stronger C++/Python path unification to reduce duplicated quantization logic
The extension build depends on a working Python + PyTorch + CUDA toolchain.
- Create and activate a clean conda env:
conda create -n bitscom python=3.12 -y
conda activate bitscom- Install base build tools:
python -m pip install --upgrade pip setuptools wheel- Install PyTorch with CUDA support (example: CUDA 13.0 wheels):
python -m pip install torch --index-url https://download.pytorch.org/whl/cu130- Optional: if CUDA/NCCL are not in default locations, export paths:
export CUDA_HOME=/usr/local/cuda
export NCCL_INCLUDE_DIR=/path/to/nccl/include
export NCCL_LIB_DIR=/path/to/nccl/lib- Quick sanity checks before building:
python -c "import torch; print(torch.__version__, torch.version.cuda)"
nvcc --versionEditable install (recommended for development):
pip install -e .If using the tested conda environment in this repo:
/home/aerith/miniforge3/envs/bitscom/bin/python -m pip install -e . --no-build-isolationCorex clang++ toolchain build (Corex CUDA at /usr/local/corex-4.4.0):
CUDA_HOME=/usr/local/corex-4.4.0 \
BITSCOM_CUDA_COMPILER=/usr/local/corex-4.4.0/bin/clang++ \
/root/miniconda3/envs/ytli_test/bin/python -m pip install -e . --no-build-isolationThe extension build now emits compile_commands.json at repo root for clangd.
Unit tests and non-distributed integration-safe tests:
pytest -qQuantization-focused tests (including CUDA path and stochastic rounding checks):
/home/aerith/miniforge3/envs/bitscom/bin/python -m pytest -q tests/test_quantization.pyPipeline-A API behavior tests:
/home/aerith/miniforge3/envs/bitscom/bin/python -m pytest -q tests/test_api.pyDistributed correctness test for pipeline-A (NCCL, 2+ GPUs):
BITSCOM_RUN_DIST=1 /home/aerith/miniforge3/envs/bitscom/bin/python -m pytest -q tests/test_pipeline_a_correctness.pyRun integration/e2e with distributed launcher:
torchrun --nproc_per_node=2 tests/test_e2e.pyRun single-GPU end-to-end training tests (no multi-GPU required):
/home/aerith/miniforge3/envs/bitscom/bin/python -m pytest -q tests/test_single_gpu_train_e2e.pyThe single-GPU e2e test prints performance metrics:
avg_step_time_msthroughput_samples_per_speak_memory_mb
To run the CIFAR10 small-step variant (10 steps), allow dataset download:
BITSCOM_ALLOW_DOWNLOAD=1 /home/aerith/miniforge3/envs/bitscom/bin/python -m pytest -q tests/test_single_gpu_train_e2e.py -k cifar10Performance tests are included but disabled by default to keep CI stable.
BITSCOM_RUN_PERF=1 pytest -q -m performanceGenerate a latency/speedup curve for quantize_tensor (CPU original path vs CUDA path):
/home/aerith/miniforge3/envs/bitscom/bin/python benchmarks/quantize_perf_curve.py --bitwidth 4 --min-pow2 10 --max-pow2 23Outputs:
benchmarks/outputs/quantize_curve_bw4.csvbenchmarks/outputs/quantize_curve_bw4.png
Preview:
Generate communication-error and training-loss comparison curves for EF vs no-EF:
/home/aerith/miniforge3/envs/bitscom/bin/python benchmarks/error_feedback_comparison.py --bitwidth 2 --steps 180 --train-steps 140 --vec-size 524288 --batch-size 256 --device cuda:0Outputs:
benchmarks/outputs/ef_benefit_curve_bw2.csvbenchmarks/outputs/ef_training_curve_bw2.csvbenchmarks/outputs/ef_comparison_bw2.png
Preview:
Generate one summary figure across multiple bitwidths (default 2/4/8):
/home/aerith/miniforge3/envs/bitscom/bin/python benchmarks/error_feedback_multibw.py --bitwidths 2 4 8 --device cuda:0 --steps 160 --train-steps 120 --vec-size 524288 --batch-size 256Key output:
benchmarks/outputs/ef_multibitwidth_summary.png
Preview:
Generate end-to-end distributed training loss curves comparing:
stochastic_rounding=Falsestochastic_rounding=True- no-compression baseline (full-precision all-reduce path)
Run (2 GPUs):
torchrun --nproc_per_node=2 benchmarks/stochastic_rounding_e2e_curve.py --bitwidth 4 --steps 160 --batch-size 128Outputs:
benchmarks/outputs/e2e_loss_curve_stochastic_vs_nocompress_bw4.csvbenchmarks/outputs/e2e_loss_curve_stochastic_vs_nocompress_bw4.png
Run distributed end-to-end comparisons across multiple model families:
- lowbit without stochastic rounding
- lowbit with stochastic rounding
- no-compression baseline
Example (2 GPUs):
torchrun --nproc_per_node=2 benchmarks/multimodel_stochastic_e2e_curve.py --models resnet50 bert gpt2 --bitwidth 4 --steps 80 --batch-size 8 --dataset-size 512Per-model outputs:
benchmarks/outputs/multimodel_resnet50_loss_curve_bw4.csvbenchmarks/outputs/multimodel_resnet50_loss_curve_bw4.pngbenchmarks/outputs/multimodel_bert_loss_curve_bw4.csvbenchmarks/outputs/multimodel_bert_loss_curve_bw4.pngbenchmarks/outputs/multimodel_gpt2_loss_curve_bw4.csvbenchmarks/outputs/multimodel_gpt2_loss_curve_bw4.png
Sweep error-feedback modes (none / legacy / ef21 / ef21_plus) across models and export per-mode loss curves plus a combined summary:
python benchmarks/error_feedback_multimodel_summary.py \
--modes none legacy ef21 ef21_plus \
--models resnet50 bert gpt2 \
--bitwidth 4 \
--nproc 2Key outputs:
benchmarks/outputs/ef_modes_resnet50_loss_curve_bw4.csvbenchmarks/outputs/ef_modes_resnet50_loss_curve_bw4.pngbenchmarks/outputs/ef_modes_bert_loss_curve_bw4.csvbenchmarks/outputs/ef_modes_bert_loss_curve_bw4.pngbenchmarks/outputs/ef_modes_gpt2_loss_curve_bw4.csvbenchmarks/outputs/ef_modes_gpt2_loss_curve_bw4.pngbenchmarks/outputs/ef_modes_throughput_summary_bw4.csvbenchmarks/outputs/ef_modes_throughput_summary_bw4.png
The script runs torchrun internally for each EF mode. If you already have
per-mode CSVs, you can re-plot without rerunning training:
python benchmarks/error_feedback_multimodel_summary.py --skip-runCompare lowbit collectives against a full-precision NCCL baseline, exporting per-step error + timing CSVs and plots.
Single bitwidth (2 GPUs):
torchrun --nproc_per_node=2 benchmarks/collective_compare.py \
--collective allreduce \
--bitwidth 4 \
--steps 60 \
--numel 262144Outputs:
benchmarks/outputs/collective_compare_allreduce_bw4.csvbenchmarks/outputs/collective_compare_allreduce_bw4.png
Multi-bitwidth sweep with summary plot:
python benchmarks/collective_compare_multibw.py \
--collective reduce_scatter \
--bitwidths 1 2 4 8 \
--steps 60 \
--numel 262144 \
--nproc 2Summary outputs:
benchmarks/outputs/collective_compare_reduce_scatter_summary.csvbenchmarks/outputs/collective_compare_reduce_scatter_summary.png
Use explicit backend options when registering:
import bitscom
# Register lowbit backend with explicit options.
bitscom.init(bitwidth=4, error_feedback=True)
# Specify an error-feedback mode (optional): none / legacy / ef21 / ef21_plus
bitscom.init(bitwidth=4, error_feedback_mode="ef21")
bitscom.init(bitwidth=4, error_feedback_mode="ef21_plus")Notes:
error_feedback=Trueis equivalent toerror_feedback_mode="legacy".error_feedback_mode="legacy"and"ef21"apply to the first-stage quantization in low-bit allreduce.error_feedback_mode="ef21_plus"also enables error feedback on the reduced-shard quantization stage.- Re-registering backend with different options in the same process raises an error by design.
When using hierarchical pipeline-A in Python (local_group + inter_group),
you can control whether local-group communication is quantized:
group.all_reduce(
tensor,
local_group=local_group,
inter_group=inter_group,
chunk_size=1 << 20,
local_quantize=False, # default: local full precision, inter lowbit
)Set local_quantize=True to keep the original behavior where local-group and
inter-group stages are both quantized.
cpp/: C++ backend and bindingspython/bitscom/: Python packagetests/: unit tests, integration tests, and performance tests


