Set Diffusion: Interpolating Token Orderings between Autoregression and Diffusion for Fast and Flexible Decoding
August 9, 2026 ยท View on GitHub
0. Setup
Setup environment
Install conda:
# For conda: https://docs.conda.io/projects/conda/en/stable/user-guide/install/linux.html
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh && \
bash miniconda.sh -b -p /opt/conda
Create the locked conda environment:
conda env create -f requirements.yaml
conda activate dllm-dev
The conda file installs Python, pip, the pinned dependencies in
requirements-lock.txt, and this package in editable mode.
To validate a fresh environment, run:
python -m pip check
python - <<'PY'
import torch
import transformers
import src
print(torch.__version__)
print(transformers.__version__)
PY
For a pip-only install, use the pinned direct requirements:
python -m pip install -r requirements.txt -e .
Use requirements-lock.txt when byte-for-byte dependency
reproduction is required. Regenerate the lockfile only as an intentional release step.
Activate an existing environment with:
conda activate dllm-dev
We also include a setup_env.sh script for runtime shell variables on
compute nodes. Run it from the repository root after the environment has been created:
source setup_env.sh
Credentials are intentionally opt-in. If you want the setup script to source private
W&B or Hugging Face settings, point DLLM_PRIVATE_ENV at a local, untracked shell file:
export WANDB__SERVICE_WAIT=600
export WANDB_ENTITY="<WANDB_ENTITY>"
export WANDB_API_KEY="<WANDB_API_KEY>"
export HUGGINGFACE_TOKEN="<HF_TOKEN>"
Then run DLLM_PRIVATE_ENV=/path/to/private_env.sh source setup_env.sh.
1. Code Organization
bash_scripts: These shell scripts can be used to reproduce the experiments from our work.configs: We use Hydra config files to organize experiments.config.yaml: Entry point for launching training experiments.eval_config.yaml: Entry point for evaluations.
scripts: The main training and evaluation scriptsscripts/composer_scripts/train_discrete_denoiser.py: This script is the main training entry point.scripts/eval: These scripts run evaluation for the translation, summarization, and math reasoning datasets, as well as any likelihood evaluation.
src:src/denoiser: During training, denoisers take in "noisy" inputs and predict clean signals. At inference, starting from a purely noisy signal, through iterative denoising, these classes produce samples that resemble data.AR: We can view autoregressive models within this paradigm. Noise is applied by masking tokens one at a time from right-to-left. Denoising is done one token at a time, left-to-right.Diffusion: We implement masked diffusion models:MDLM: Standard masked diffusion.BD3LM: Block diffusion models.SetDLM: Set diffusion models.
src/backbone: These are the underlying neural networks that take in noisy inputs and produce logits. Each denoiser is parameterized by a backbone. The denoiser can optionally post-process the logit outputs of the backbone to produce log-probs over the clean sequence.
2. Reproducing Experiments
The shell scripts provided in bash_scripts can be used to reproduce
the training and evaluations from our work.
- For training, the files follow a convention where the dataset and denoiser class are
specified.
For example, to train SetDLM on the GSM8K dataset, use
run_train_setdlm_gsm8k.sh. - Once models have been trained or downloaded, the provided evaluation scripts can be used
to reproduce the reported metrics from our work. For example, to evaluate GSM8K models,
use
run_lm_eval_harness.sh. The task-specific wrappers below document the supported evaluation entry points. Plotting utilities are kept out of this release repo; generate plots from exported metrics/TSV artifacts downstream.
Evaluation scripts resolve checkpoint keys through bash_scripts/eval_model_paths.sh.
Select a known checkpoint with EVAL_MODEL_KEY, or pass an explicit HF id or local
checkpoint path in MODEL_PATH:
# Resolve to kuleshov-group/setdlm-gsm8k-smax32.
EVAL_MODEL_KEY=gsm8k:setdlm-smax32 bash bash_scripts/run_lm_eval_harness.sh
# Explicit HF ids and local paths are also accepted.
MODEL_PATH=kuleshov-group/cnndm-setdlm-smax16 bash bash_scripts/run_seq2seq_eval_cnndm.sh
MODEL_PATH=/share/kuleshov/ma2238/runs/dllm-dev/<run-dir> bash bash_scripts/run_lm_eval_harness.sh
Dataset configs read from DLLM_DATA_DIR and default to data/. Set
DLLM_DATA_DIR=/path/to/datasets when cached datasets live elsewhere. Evaluation scripts
write outputs under outputs/ by default and accept checkpoint-related overrides such as
MODEL_PATH, EVAL_MODEL_KEY, CKPT_FILE or CKPT, and USE_EMA. LM1B_MODEL_KEY
and LM1B_MODEL_PATH are accepted by the LM1B likelihood wrapper.
GSM8K Distillation Data
The GSM8K training wrappers for AR, MDLM, BD3LM, and SetDLM use distilled teacher answers saved as preprocessed Hugging Face datasets. Build them before launching GSM8K distillation training:
bash bash_scripts/run_build_gsm8k_distill.sh
By default this writes:
outputs/distillation/Qwen3-32B-AWQ/gsm8k_train
outputs/distillation/Qwen3-32B-AWQ/gsm8k_eval
Set DLLM_DISTILL_DATA_DIR if you want the datasets somewhere else, and use the
same value when launching training:
DLLM_DISTILL_DATA_DIR=/path/to/Qwen3-32B-AWQ bash bash_scripts/run_build_gsm8k_distill.sh
DLLM_DISTILL_DATA_DIR=/path/to/Qwen3-32B-AWQ NUM_VISIBLE_DEVICES=8 bash bash_scripts/run_train_setdlm_gsm8k.sh
The builder defaults to Qwen/Qwen3-32B-AWQ as the teacher and
Qwen/Qwen3-1.7B-Base as the student tokenizer. It saves the same artifact
shape used by the local L=1024 GSM8K distillation datasets: input_ids plus
index, final sequences capped at 1024 tokens, and chat rows terminated with
<|im_end|>. Override the teacher and student tokenizer with
DISTILL_TEACHER_MODEL and DISTILL_STUDENT_TOKENIZER. For a fast smoke test
that validates the preprocessing path without loading the teacher model, set
DISTILL_USE_GOLD_ANSWERS=true; this does not reproduce the paper distillation
data.
Evaluation scripts are provided for the following tasks:
- Text summarization:
run_seq2seq_eval_cnndm.sh - Mathematical reasoning:
run_lm_eval_harness.sh,run_likelihood_eval_gsm8k.sh - Likelihood estimation:
run_likelihood_eval_owt.sh,run_likelihood_eval_lm1b.sh - Multiple-choice commonsense benchmarks (trained on OpenWebText):
run_mcqa_eval_owt.sh - Infilling (trained on OpenWebText):
run_seq2seq_eval_infill_nlp.sh - Unconditional generation (trained on OpenWebText):
run_uncond_gen_ppl_owt.sh
For full experiment sweeps, scripts/eval/repro_suite_runner.py
builds the evaluation matrix and uses the same HF-first checkpoint resolver, so generated
commands and expected output paths agree with the shell wrappers.
Paper H100 Throughput Reproduction
For the H100 throughput numbers reported in the paper, use the paper-specific wrappers:
repro_paper_infill_rouge_tput_h100.shfor ROCStories infilling.repro_paper_cnndm_tput_h100.shfor CNN/DailyMail summarization.repro_paper_gsm8k_tput_h100.shfor GSM8K throughput.
All three wrappers use 50 warmup examples. CNN/DailyMail and ROCStories use
1000 measured examples; the GSM8K helper defaults to 200 measured examples and
accepts EVAL_MODEL_KEY, MODEL_PATH, CONFIDENCE_THRESHOLD, BLOCK_SIZE, and
MAX_WINDOW_SIZE overrides for the other Pareto points.
The MCQA evaluation flow uses Hydra overrides in the same style as the other eval
frameworks, for example +eval/mcqa@task=all or +eval/mcqa@task=hellaswag.
It evaluates the validation splits of HellaSwag, PIQA, and Social IQa with
continuation scoring rather than greedy generation, writes per-example predictions
and option scores to predictions.json, and saves aggregate accuracies plus a
summary table to metrics.json / metrics.txt. By default, answer options are
ranked by average log-probability per answer token to reduce length bias.
3. Hugging Face Checkpoints
SetDLM Hugging Face repo ids use smax{2 * desired_block_size} naming. For example,
SetDLM-smax32 is published as *-setdlm-smax32. The GSM8K SetDLM release ids are:
kuleshov-group/setdlm-gsm8k-smax8kuleshov-group/setdlm-gsm8k-smax16kuleshov-group/setdlm-gsm8k-smax32
The corresponding CNN/DM, OWT, and LM1B ids are:
kuleshov-group/cnndm-setdlm-smax8,kuleshov-group/cnndm-setdlm-smax16,kuleshov-group/cnndm-setdlm-smax32kuleshov-group/owt-setdlm-smax8,kuleshov-group/owt-setdlm-smax16,kuleshov-group/owt-setdlm-smax32kuleshov-group/lm1b-setdlm-smax8,kuleshov-group/lm1b-setdlm-smax16,kuleshov-group/lm1b-setdlm-smax32
Other evaluated checkpoints use the kuleshov-group/<dataset>-<model> naming
scheme, for example kuleshov-group/owt-bd3lm-s16. The resolver accepts either
these HF ids or compact keys such as cnndm:setdlm-smax16, owt:bd3lm-s16, and
lm1b:ar. For exact GSM8K SetDLM Pareto reproduction, use the repo evaluation
loader/scripts rather than plain AutoModel.from_pretrained, because the loader
normalizes legacy checkpoint config and eval-time SetDLM noise/cache-order settings.
Citation
@article{arriola2026setdiffusion,
title={Set Diffusion: Interpolating Token Orderings Between Autoregression and Diffusion for Fast and Flexible Decoding},
author={Arriola, Marianne and Kuleshov, Volodymyr},
booktitle={The Forty-Third International Conference on Machine Learning},
year={2026},
url={https://arxiv.org/abs/2607.01775}
}