gpu-goblin / tests /fixtures /cached_audit.json
sasukeUchiha123's picture
Upload tests/fixtures/cached_audit.json with huggingface_hub
930182d verified
Raw
History Blame Contribute Delete
67.1 kB
[
{
"type": "thought",
"data": {
"text": "User uploaded a Qwen2.5 LoRA fine-tuning script. I'll start by parsing the configuration and redacting any secrets, then profile a short run on MI300X before consulting the ROCm playbook for known wins."
}
},
{
"type": "tool_call",
"data": {
"id": "tc-1",
"name": "parse_config",
"input": {
"file_path": "workloads/train_qwen_lora.py"
}
}
},
{
"type": "tool_result",
"data": {
"id": "tc-1",
"name": "parse_config",
"ok": true,
"result": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "fp16",
"optimizer": "adamw_torch",
"attention_impl": "eager",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
}
}
},
{
"type": "tool_call",
"data": {
"id": "tc-2",
"name": "profile_run",
"input": {
"config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "fp16",
"optimizer": "adamw_torch",
"attention_impl": "eager",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"steps": 10
}
}
},
{
"type": "tool_result",
"data": {
"id": "tc-2",
"name": "profile_run",
"ok": true,
"result": {
"steps": 10,
"tokens_per_sec": 142.0,
"mfu_pct": 24.0,
"hbm_peak_gb": 73.0,
"hbm_avg_gb": 61.0,
"gpu_util_pct": 46.0,
"top_kernels": [
{
"name": "aten::matmul (fp16)",
"pct_time": 38.0
},
{
"name": "aten::scaled_dot_product_attention (eager)",
"pct_time": 24.0
},
{
"name": "aten::layer_norm",
"pct_time": 8.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 5.0
},
{
"name": "aten::copy_ (h2d)",
"pct_time": 11.0
}
],
"attention_kernel_loaded": "eager",
"waste_budget": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"warnings": [
"Attention kernel is 'eager'; flash_rocm or sdpa would be much faster.",
"HBM utilization 38% suggests batch_size is leaving memory on the floor."
],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
}
}
},
{
"type": "thought",
"data": {
"text": "Profile shows 142 tok/s at 24% MFU \u2014 the precision_path and kernel_shape buckets are heavy. Querying the ROCm KB for matching rules."
}
},
{
"type": "tool_call",
"data": {
"id": "tc-3",
"name": "query_rocm_kb",
"input": {
"symptom": "fp16 with eager attention and zero dataloader workers on MI300X",
"top_k": 6
}
}
},
{
"type": "tool_result",
"data": {
"id": "tc-3",
"name": "query_rocm_kb",
"ok": true,
"result": {
"rules": [
{
"id": "precision.bf16_over_fp16_on_mi300x",
"category": "precision",
"targets_bucket": "precision_path",
"symptom": "fp16 used on MI300X / CDNA3",
"detect": {
"precision": "fp16"
},
"transform": {
"precision": "bf16"
},
"expected_recovery_fraction": 0.85,
"expected_impact": "MI300X CDNA3 matrix cores execute bf16 at the same throughput as fp16 with strictly better numerical stability. Reduces NaN risk in long runs.",
"rocm_version_min": "6.0",
"citation": "ROCm MI300X Optimization Guide \u00a73.2 \u2014 bf16 vs fp16"
},
{
"id": "attention.flash_rocm_over_eager",
"category": "attention",
"targets_bucket": "kernel_shape",
"symptom": "naive (eager) attention on MI300X \u2014 no flash kernel loaded",
"detect": {
"attention_impl": "eager"
},
"transform": {
"attention_impl": "flash_rocm"
},
"expected_recovery_fraction": 0.7,
"expected_impact": "Use the ROCm-validated flash-attention kernel (via Optimum-AMD or PyTorch SDPA backend). Eliminates O(seq_len^2) attention memory; typically 2-3x faster on MI300X for seq_len >= 1024.",
"rocm_version_min": "6.0",
"citation": "AMD ROCm vLLM/Optimum-AMD docs \u2014 Flash Attention validated on MI300"
}
]
}
}
},
{
"type": "tool_call",
"data": {
"id": "tc-4",
"name": "propose_patch",
"input": {
"config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "fp16",
"optimizer": "adamw_torch",
"attention_impl": "eager",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"rules": [
{
"id": "precision.bf16_over_fp16_on_mi300x",
"category": "precision",
"targets_bucket": "precision_path",
"symptom": "fp16 used on MI300X / CDNA3",
"detect": {
"precision": "fp16"
},
"transform": {
"precision": "bf16"
},
"expected_recovery_fraction": 0.85,
"expected_impact": "MI300X CDNA3 matrix cores execute bf16 at the same throughput as fp16 with strictly better numerical stability. Reduces NaN risk in long runs.",
"rocm_version_min": "6.0",
"citation": "ROCm MI300X Optimization Guide \u00a73.2 \u2014 bf16 vs fp16"
},
{
"id": "attention.flash_rocm_over_eager",
"category": "attention",
"targets_bucket": "kernel_shape",
"symptom": "naive (eager) attention on MI300X \u2014 no flash kernel loaded",
"detect": {
"attention_impl": "eager"
},
"transform": {
"attention_impl": "flash_rocm"
},
"expected_recovery_fraction": 0.7,
"expected_impact": "Use the ROCm-validated flash-attention kernel (via Optimum-AMD or PyTorch SDPA backend). Eliminates O(seq_len^2) attention memory; typically 2-3x faster on MI300X for seq_len >= 1024.",
"rocm_version_min": "6.0",
"citation": "AMD ROCm vLLM/Optimum-AMD docs \u2014 Flash Attention validated on MI300"
}
],
"metrics": {
"steps": 10,
"tokens_per_sec": 142.0,
"mfu_pct": 24.0,
"hbm_peak_gb": 73.0,
"hbm_avg_gb": 61.0,
"gpu_util_pct": 46.0,
"top_kernels": [
{
"name": "aten::matmul (fp16)",
"pct_time": 38.0
},
{
"name": "aten::scaled_dot_product_attention (eager)",
"pct_time": 24.0
},
{
"name": "aten::layer_norm",
"pct_time": 8.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 5.0
},
{
"name": "aten::copy_ (h2d)",
"pct_time": 11.0
}
],
"attention_kernel_loaded": "eager",
"waste_budget": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"warnings": [
"Attention kernel is 'eager'; flash_rocm or sdpa would be much faster.",
"HBM utilization 38% suggests batch_size is leaving memory on the floor."
],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
}
}
}
},
{
"type": "tool_result",
"data": {
"id": "tc-4",
"name": "propose_patch",
"ok": true,
"result": {
"new_config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "bf16",
"optimizer": "adamw_torch",
"attention_impl": "flash_rocm",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"diff": "- attention_impl: 'eager'\n+ attention_impl: 'flash_rocm'\n- precision: 'fp16'\n+ precision: 'bf16'",
"rationale": [
{
"rule_id": "precision.bf16_over_fp16_on_mi300x",
"rationale": "MI300X CDNA3 matrix cores execute bf16 at the same throughput as fp16 with strictly better numerical stability. Reduces NaN risk in long runs.",
"citation": "ROCm MI300X Optimization Guide \u00a73.2 \u2014 bf16 vs fp16",
"targets_bucket": "precision_path",
"estimated_recovery_seconds": 0.0935
},
{
"rule_id": "attention.flash_rocm_over_eager",
"rationale": "Use the ROCm-validated flash-attention kernel (via Optimum-AMD or PyTorch SDPA backend). Eliminates O(seq_len^2) attention memory; typically 2-3x faster on MI300X for seq_len >= 1024.",
"citation": "AMD ROCm vLLM/Optimum-AMD docs \u2014 Flash Attention validated on MI300",
"targets_bucket": "kernel_shape",
"estimated_recovery_seconds": 0.041999999999999996
}
],
"expected_speedup_low": 1.04,
"expected_speedup_high": 1.31,
"confidence": 0.85
}
}
},
{
"type": "tool_call",
"data": {
"id": "tc-5",
"name": "benchmark",
"input": {
"config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "fp16",
"optimizer": "adamw_torch",
"attention_impl": "eager",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"steps": 50
}
}
},
{
"type": "tool_result",
"data": {
"id": "tc-5",
"name": "benchmark",
"ok": true,
"result": {
"steps": 50,
"tokens_per_sec": 142.0,
"mfu_pct": 24.0,
"hbm_peak_gb": 73.0,
"hbm_avg_gb": 61.0,
"gpu_util_pct": 46.0,
"top_kernels": [
{
"name": "aten::matmul (fp16)",
"pct_time": 38.0
},
{
"name": "aten::scaled_dot_product_attention (eager)",
"pct_time": 24.0
},
{
"name": "aten::layer_norm",
"pct_time": 8.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 5.0
},
{
"name": "aten::copy_ (h2d)",
"pct_time": 11.0
}
],
"attention_kernel_loaded": "eager",
"waste_budget": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"warnings": [
"Attention kernel is 'eager'; flash_rocm or sdpa would be much faster.",
"HBM utilization 38% suggests batch_size is leaving memory on the floor."
],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
}
}
},
{
"type": "tool_call",
"data": {
"id": "tc-6",
"name": "benchmark",
"input": {
"config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "bf16",
"optimizer": "adamw_torch",
"attention_impl": "flash_rocm",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"steps": 50
}
}
},
{
"type": "tool_result",
"data": {
"id": "tc-6",
"name": "benchmark",
"ok": true,
"result": {
"steps": 50,
"tokens_per_sec": 318.0,
"mfu_pct": 51.0,
"hbm_peak_gb": 168.0,
"hbm_avg_gb": 152.0,
"gpu_util_pct": 86.0,
"top_kernels": [
{
"name": "aten::matmul (bf16)",
"pct_time": 46.0
},
{
"name": "flash_attn_rocm_fwd",
"pct_time": 19.0
},
{
"name": "flash_attn_rocm_bwd",
"pct_time": 14.0
},
{
"name": "aten::layer_norm",
"pct_time": 7.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 4.0
}
],
"attention_kernel_loaded": "flash_rocm",
"waste_budget": {
"useful_gpu": 0.78,
"data_wait": 0.04,
"host_gap": 0.05,
"comm_excess": 0.0,
"memory_headroom": 0.04,
"precision_path": 0.02,
"kernel_shape": 0.03
},
"warnings": [],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
}
}
},
{
"type": "tool_call",
"data": {
"id": "tc-7",
"name": "compare_runs",
"input": {
"workload_name": "Qwen2.5-7B LoRA fine-tune",
"before": {
"steps": 50,
"tokens_per_sec": 142.0,
"mfu_pct": 24.0,
"hbm_peak_gb": 73.0,
"hbm_avg_gb": 61.0,
"gpu_util_pct": 46.0,
"top_kernels": [
{
"name": "aten::matmul (fp16)",
"pct_time": 38.0
},
{
"name": "aten::scaled_dot_product_attention (eager)",
"pct_time": 24.0
},
{
"name": "aten::layer_norm",
"pct_time": 8.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 5.0
},
{
"name": "aten::copy_ (h2d)",
"pct_time": 11.0
}
],
"attention_kernel_loaded": "eager",
"waste_budget": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"warnings": [
"Attention kernel is 'eager'; flash_rocm or sdpa would be much faster.",
"HBM utilization 38% suggests batch_size is leaving memory on the floor."
],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
},
"after": {
"steps": 50,
"tokens_per_sec": 318.0,
"mfu_pct": 51.0,
"hbm_peak_gb": 168.0,
"hbm_avg_gb": 152.0,
"gpu_util_pct": 86.0,
"top_kernels": [
{
"name": "aten::matmul (bf16)",
"pct_time": 46.0
},
{
"name": "flash_attn_rocm_fwd",
"pct_time": 19.0
},
{
"name": "flash_attn_rocm_bwd",
"pct_time": 14.0
},
{
"name": "aten::layer_norm",
"pct_time": 7.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 4.0
}
],
"attention_kernel_loaded": "flash_rocm",
"waste_budget": {
"useful_gpu": 0.78,
"data_wait": 0.04,
"host_gap": 0.05,
"comm_excess": 0.0,
"memory_headroom": 0.04,
"precision_path": 0.02,
"kernel_shape": 0.03
},
"warnings": [],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
},
"patch": {
"new_config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "bf16",
"optimizer": "adamw_torch",
"attention_impl": "flash_rocm",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"diff": "- attention_impl: 'eager'\n+ attention_impl: 'flash_rocm'\n- precision: 'fp16'\n+ precision: 'bf16'",
"rationale": [
{
"rule_id": "precision.bf16_over_fp16_on_mi300x",
"rationale": "MI300X CDNA3 matrix cores execute bf16 at the same throughput as fp16 with strictly better numerical stability. Reduces NaN risk in long runs.",
"citation": "ROCm MI300X Optimization Guide \u00a73.2 \u2014 bf16 vs fp16",
"targets_bucket": "precision_path",
"estimated_recovery_seconds": 0.0935
},
{
"rule_id": "attention.flash_rocm_over_eager",
"rationale": "Use the ROCm-validated flash-attention kernel (via Optimum-AMD or PyTorch SDPA backend). Eliminates O(seq_len^2) attention memory; typically 2-3x faster on MI300X for seq_len >= 1024.",
"citation": "AMD ROCm vLLM/Optimum-AMD docs \u2014 Flash Attention validated on MI300",
"targets_bucket": "kernel_shape",
"estimated_recovery_seconds": 0.041999999999999996
}
],
"expected_speedup_low": 1.04,
"expected_speedup_high": 1.31,
"confidence": 0.85
}
}
}
},
{
"type": "tool_result",
"data": {
"id": "tc-7",
"name": "compare_runs",
"ok": true,
"result": {
"workload_name": "Qwen2.5-7B LoRA fine-tune",
"before": {
"steps": 50,
"tokens_per_sec": 142.0,
"mfu_pct": 24.0,
"hbm_peak_gb": 73.0,
"hbm_avg_gb": 61.0,
"gpu_util_pct": 46.0,
"top_kernels": [
{
"name": "aten::matmul (fp16)",
"pct_time": 38.0
},
{
"name": "aten::scaled_dot_product_attention (eager)",
"pct_time": 24.0
},
{
"name": "aten::layer_norm",
"pct_time": 8.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 5.0
},
{
"name": "aten::copy_ (h2d)",
"pct_time": 11.0
}
],
"attention_kernel_loaded": "eager",
"waste_budget": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"warnings": [
"Attention kernel is 'eager'; flash_rocm or sdpa would be much faster.",
"HBM utilization 38% suggests batch_size is leaving memory on the floor."
],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
},
"after": {
"steps": 50,
"tokens_per_sec": 318.0,
"mfu_pct": 51.0,
"hbm_peak_gb": 168.0,
"hbm_avg_gb": 152.0,
"gpu_util_pct": 86.0,
"top_kernels": [
{
"name": "aten::matmul (bf16)",
"pct_time": 46.0
},
{
"name": "flash_attn_rocm_fwd",
"pct_time": 19.0
},
{
"name": "flash_attn_rocm_bwd",
"pct_time": 14.0
},
{
"name": "aten::layer_norm",
"pct_time": 7.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 4.0
}
],
"attention_kernel_loaded": "flash_rocm",
"waste_budget": {
"useful_gpu": 0.78,
"data_wait": 0.04,
"host_gap": 0.05,
"comm_excess": 0.0,
"memory_headroom": 0.04,
"precision_path": 0.02,
"kernel_shape": 0.03
},
"warnings": [],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
},
"patch": {
"new_config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "bf16",
"optimizer": "adamw_torch",
"attention_impl": "flash_rocm",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"diff": "- attention_impl: 'eager'\n+ attention_impl: 'flash_rocm'\n- precision: 'fp16'\n+ precision: 'bf16'",
"rationale": [
{
"rule_id": "precision.bf16_over_fp16_on_mi300x",
"rationale": "MI300X CDNA3 matrix cores execute bf16 at the same throughput as fp16 with strictly better numerical stability. Reduces NaN risk in long runs.",
"citation": "ROCm MI300X Optimization Guide \u00a73.2 \u2014 bf16 vs fp16",
"targets_bucket": "precision_path",
"estimated_recovery_seconds": 0.0935
},
{
"rule_id": "attention.flash_rocm_over_eager",
"rationale": "Use the ROCm-validated flash-attention kernel (via Optimum-AMD or PyTorch SDPA backend). Eliminates O(seq_len^2) attention memory; typically 2-3x faster on MI300X for seq_len >= 1024.",
"citation": "AMD ROCm vLLM/Optimum-AMD docs \u2014 Flash Attention validated on MI300",
"targets_bucket": "kernel_shape",
"estimated_recovery_seconds": 0.041999999999999996
}
],
"expected_speedup_low": 1.04,
"expected_speedup_high": 1.31,
"confidence": 0.85
},
"metric_deltas": [
{
"name": "tokens_per_sec",
"before": 142.0,
"after": 318.0,
"unit": "tok/s"
},
{
"name": "mfu_pct",
"before": 24.0,
"after": 51.0,
"unit": "%"
},
{
"name": "hbm_peak_gb",
"before": 73.0,
"after": 168.0,
"unit": "GB"
},
{
"name": "gpu_util_pct",
"before": 46.0,
"after": 86.0,
"unit": "%"
}
],
"waste_budget_before": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"waste_budget_after": {
"useful_gpu": 0.78,
"data_wait": 0.04,
"host_gap": 0.05,
"comm_excess": 0.0,
"memory_headroom": 0.04,
"precision_path": 0.02,
"kernel_shape": 0.03
},
"speedup_actual": 2.24,
"speedup_predicted_low": 1.04,
"speedup_predicted_high": 1.31,
"confidence": 0.85,
"summary_line": "Tokens/sec: 142 \u2192 318 (2.24\u00d7). MFU: 24% \u2192 51%.",
"validity_footer": "Recommendations validated against MI300X with the observed ROCm and PyTorch versions. Re-run the audit if you change model, hardware, or framework version."
}
}
},
{
"type": "final_report",
"data": {
"report": {
"workload_name": "Qwen2.5-7B LoRA fine-tune",
"before": {
"steps": 50,
"tokens_per_sec": 142.0,
"mfu_pct": 24.0,
"hbm_peak_gb": 73.0,
"hbm_avg_gb": 61.0,
"gpu_util_pct": 46.0,
"top_kernels": [
{
"name": "aten::matmul (fp16)",
"pct_time": 38.0
},
{
"name": "aten::scaled_dot_product_attention (eager)",
"pct_time": 24.0
},
{
"name": "aten::layer_norm",
"pct_time": 8.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 5.0
},
{
"name": "aten::copy_ (h2d)",
"pct_time": 11.0
}
],
"attention_kernel_loaded": "eager",
"waste_budget": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"warnings": [
"Attention kernel is 'eager'; flash_rocm or sdpa would be much faster.",
"HBM utilization 38% suggests batch_size is leaving memory on the floor."
],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
},
"after": {
"steps": 50,
"tokens_per_sec": 318.0,
"mfu_pct": 51.0,
"hbm_peak_gb": 168.0,
"hbm_avg_gb": 152.0,
"gpu_util_pct": 86.0,
"top_kernels": [
{
"name": "aten::matmul (bf16)",
"pct_time": 46.0
},
{
"name": "flash_attn_rocm_fwd",
"pct_time": 19.0
},
{
"name": "flash_attn_rocm_bwd",
"pct_time": 14.0
},
{
"name": "aten::layer_norm",
"pct_time": 7.0
},
{
"name": "aten::cross_entropy_loss",
"pct_time": 4.0
}
],
"attention_kernel_loaded": "flash_rocm",
"waste_budget": {
"useful_gpu": 0.78,
"data_wait": 0.04,
"host_gap": 0.05,
"comm_excess": 0.0,
"memory_headroom": 0.04,
"precision_path": 0.02,
"kernel_shape": 0.03
},
"warnings": [],
"rocm_version": "6.1.0",
"pytorch_version": "2.3.0+rocm6.1",
"runner_kind": "fake"
},
"patch": {
"new_config": {
"model_name": "Qwen/Qwen2.5-7B-Instruct",
"batch_size": 4,
"grad_accum_steps": 8,
"seq_len": 1024,
"precision": "bf16",
"optimizer": "adamw_torch",
"attention_impl": "flash_rocm",
"gradient_checkpointing": false,
"lora_rank": 16,
"dataloader_workers": 0,
"dataloader_pin_memory": false,
"dataloader_prefetch_factor": 2,
"dataloader_persistent_workers": false,
"torch_compile": false,
"lr": 0.0002,
"warmup_steps": 100,
"env_vars": {
"HF_TOKEN": "hf_aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"HSA_FORCE_FINE_GRAIN_PCIE": "1",
"MIOPEN_FIND_MODE": "3"
},
"extras": {
"lora.lora_alpha": 32,
"lora.target_modules": [
"q_proj",
"v_proj"
],
"lora.lora_dropout": 0.05,
"lora.bias": "none",
"lora.task_type": "CAUSAL_LM",
"batch_size": 4,
"output_dir": "./out",
"num_train_epochs": 3,
"logging_steps": 10,
"save_steps": 500,
"report_to": "none",
"push_to_hub": false
},
"raw_source": "# GPU Goblin canonical demo workload.\n#\n# Qwen2.5-7B-Instruct + LoRA fine-tune on the alpaca-cleaned dataset, staged with\n# *deliberately* sub-optimal defaults so the goblin has something to fix in\n# the demo. This script does NOT need to actually execute on a host \u2014 it\n# exists so `parse_config` can extract a realistic WorkloadConfig from it.\n#\n# Expected findings when audited:\n# - precision.bf16_over_fp16_on_mi300x (fp16=True)\n# - attention.flash_rocm_over_eager (attn_implementation=\"eager\")\n# - data.dataloader_workers_zero (dataloader_num_workers=0)\n# - memory.batch_too_small_for_192gb (per_device_train_batch_size=4)\n\nimport os\n\nimport torch\nfrom datasets import load_dataset\nfrom peft import LoraConfig, get_peft_model\nfrom torch.utils.data import DataLoader\nfrom transformers import (\n AutoModelForCausalLM,\n AutoTokenizer,\n Trainer,\n TrainingArguments,\n)\n\n# A redactable secret so parse_config has something to scrub during the demo.\nos.environ[\"HF_TOKEN\"] = \"<REDACTED:hf_token>\"\nHF_TOKEN = os.environ[\"HF_TOKEN\"]\n\n# ROCm-flavored env knobs the agent should pick up into env_vars.\nos.environ[\"HSA_FORCE_FINE_GRAIN_PCIE\"] = \"1\"\nos.environ[\"MIOPEN_FIND_MODE\"] = \"3\"\n\nMODEL_ID = \"Qwen/Qwen2.5-7B-Instruct\"\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN)\nmodel = AutoModelForCausalLM.from_pretrained(\n MODEL_ID,\n torch_dtype=torch.float16,\n attn_implementation=\"eager\", # naive attention -- goblin should swap to flash_rocm\n token=HF_TOKEN,\n)\n\n# LoRA \u2014 rank 16, attached to attention projections.\nlora_config = LoraConfig(\n r=16,\n lora_alpha=32,\n target_modules=[\"q_proj\", \"v_proj\"],\n lora_dropout=0.05,\n bias=\"none\",\n task_type=\"CAUSAL_LM\",\n)\nmodel = get_peft_model(model, lora_config)\n\ndataset = load_dataset(\"yahma/alpaca-cleaned\", split=\"train\")\n\n# Hand-rolled DataLoader so parse_config sees the dataloader kwargs explicitly.\ntrain_loader = DataLoader(\n dataset,\n batch_size=4,\n num_workers=0, # leaves the GPU starved during training -- data_wait waste\n pin_memory=False,\n prefetch_factor=2,\n persistent_workers=False,\n)\n\ntraining_args = TrainingArguments(\n output_dir=\"./out\",\n per_device_train_batch_size=4, # leaves HBM on the floor at 192 GB\n gradient_accumulation_steps=8,\n num_train_epochs=3,\n learning_rate=2e-4,\n warmup_steps=100,\n fp16=True, # bf16 is the right call on CDNA3\n optim=\"adamw_torch\",\n logging_steps=10,\n save_steps=500,\n dataloader_num_workers=0,\n dataloader_pin_memory=False,\n gradient_checkpointing=False,\n torch_compile=False,\n report_to=\"none\",\n push_to_hub=False,\n)\n\ntrainer = Trainer(\n model=model,\n args=training_args,\n train_dataset=dataset,\n tokenizer=tokenizer,\n)\n\nif __name__ == \"__main__\":\n trainer.train()\n",
"redactions": [
"hf_token"
]
},
"diff": "- attention_impl: 'eager'\n+ attention_impl: 'flash_rocm'\n- precision: 'fp16'\n+ precision: 'bf16'",
"rationale": [
{
"rule_id": "precision.bf16_over_fp16_on_mi300x",
"rationale": "MI300X CDNA3 matrix cores execute bf16 at the same throughput as fp16 with strictly better numerical stability. Reduces NaN risk in long runs.",
"citation": "ROCm MI300X Optimization Guide \u00a73.2 \u2014 bf16 vs fp16",
"targets_bucket": "precision_path",
"estimated_recovery_seconds": 0.0935
},
{
"rule_id": "attention.flash_rocm_over_eager",
"rationale": "Use the ROCm-validated flash-attention kernel (via Optimum-AMD or PyTorch SDPA backend). Eliminates O(seq_len^2) attention memory; typically 2-3x faster on MI300X for seq_len >= 1024.",
"citation": "AMD ROCm vLLM/Optimum-AMD docs \u2014 Flash Attention validated on MI300",
"targets_bucket": "kernel_shape",
"estimated_recovery_seconds": 0.041999999999999996
}
],
"expected_speedup_low": 1.04,
"expected_speedup_high": 1.31,
"confidence": 0.85
},
"metric_deltas": [
{
"name": "tokens_per_sec",
"before": 142.0,
"after": 318.0,
"unit": "tok/s"
},
{
"name": "mfu_pct",
"before": 24.0,
"after": 51.0,
"unit": "%"
},
{
"name": "hbm_peak_gb",
"before": 73.0,
"after": 168.0,
"unit": "GB"
},
{
"name": "gpu_util_pct",
"before": 46.0,
"after": 86.0,
"unit": "%"
}
],
"waste_budget_before": {
"useful_gpu": 0.42,
"data_wait": 0.21,
"host_gap": 0.06,
"comm_excess": 0.0,
"memory_headroom": 0.14,
"precision_path": 0.11,
"kernel_shape": 0.06
},
"waste_budget_after": {
"useful_gpu": 0.78,
"data_wait": 0.04,
"host_gap": 0.05,
"comm_excess": 0.0,
"memory_headroom": 0.04,
"precision_path": 0.02,
"kernel_shape": 0.03
},
"speedup_actual": 2.24,
"speedup_predicted_low": 1.04,
"speedup_predicted_high": 1.31,
"confidence": 0.85,
"summary_line": "Tokens/sec: 142 \u2192 318 (2.24\u00d7). MFU: 24% \u2192 51%.",
"validity_footer": "Recommendations validated against MI300X with the observed ROCm and PyTorch versions. Re-run the audit if you change model, hardware, or framework version."
}
}
}
]