170 lines
5.0 KiB
Python
170 lines
5.0 KiB
Python
import concurrent.futures as cf
|
|
import os
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from itertools import product
|
|
|
|
import tvm
|
|
|
|
from mlc_llm.model import MODEL_PRESETS
|
|
from mlc_llm.model import MODELS as SUPPORTED_MODELS
|
|
from mlc_llm.quantization import QUANTIZATION as SUPPORTED_QUANTS
|
|
from mlc_llm.support.constants import MLC_TEMP_DIR
|
|
|
|
OPT_LEVEL = "O2"
|
|
DEVICE2TARGET = {
|
|
"cuda": {
|
|
"kind": "cuda",
|
|
"arch": "sm_86",
|
|
"max_threads_per_block": 1024,
|
|
"max_num_threads": 1024,
|
|
"max_shared_memory_per_block": 49152,
|
|
"thread_warp_size": 32,
|
|
},
|
|
"rocm": {
|
|
"kind": "rocm",
|
|
"mtriple": "amdgcn-amd-amdhsa-hcc",
|
|
"mcpu": "gfx1100",
|
|
"thread_warp_size": 32,
|
|
"max_threads_per_block": 1024,
|
|
"max_num_threads": 256,
|
|
"max_shared_memory_per_block": 65536,
|
|
},
|
|
"vulkan": {
|
|
"kind": "vulkan",
|
|
"max_threads_per_block": 1024,
|
|
"max_num_threads": 256,
|
|
"max_shared_memory_per_block": 32768,
|
|
"thread_warp_size": 1,
|
|
"supports_float32": 1,
|
|
"supports_float16": 1,
|
|
"supports_int64": 1,
|
|
"supports_int32": 1,
|
|
"supports_int16": 1,
|
|
"supports_int8": 1,
|
|
"supports_16bit_buffer": 1,
|
|
},
|
|
"metal": "metal",
|
|
"wasm": "webgpu",
|
|
"android": "android",
|
|
"ios": "iphone",
|
|
}
|
|
DEVICE2SUFFIX = {
|
|
"cuda": "so",
|
|
"rocm": "so",
|
|
"vulkan": "so",
|
|
"metal": "dylib",
|
|
"wasm": "wasm",
|
|
"android": "tar",
|
|
"ios": "tar",
|
|
}
|
|
MODELS = list(MODEL_PRESETS.keys())
|
|
QUANTS = [ # TODO(@junrushao): use `list(mlc_llm.quantization.QUANTIZATION.keys())`
|
|
"q0f16",
|
|
"q0f32",
|
|
"q3f16_1",
|
|
"q4f16_1",
|
|
"q4f32_1",
|
|
"q4f16_ft",
|
|
]
|
|
TENSOR_PARALLEL_SHARDS = [
|
|
1,
|
|
]
|
|
|
|
|
|
def run_command(log_file, cmd):
|
|
with open(log_file, "w", encoding="utf-8") as file:
|
|
subprocess.check_call(
|
|
cmd,
|
|
stdout=file,
|
|
stderr=subprocess.STDOUT,
|
|
)
|
|
|
|
|
|
def test_model_compile():
|
|
device = sys.argv[1]
|
|
num_workers = int(sys.argv[2])
|
|
target = DEVICE2TARGET[device]
|
|
if not isinstance(target, str):
|
|
target = str(tvm.target.Target(target))
|
|
suffix = DEVICE2SUFFIX[device]
|
|
|
|
passed_cmds = []
|
|
failed_cmds = []
|
|
with tempfile.TemporaryDirectory(dir=MLC_TEMP_DIR) as tmp_dir:
|
|
with cf.ProcessPoolExecutor(max_workers=num_workers) as executor:
|
|
log_files = []
|
|
cmds = []
|
|
futures = []
|
|
for idx, (model, quant, tp_shard) in enumerate(
|
|
product(
|
|
MODELS,
|
|
QUANTS,
|
|
TENSOR_PARALLEL_SHARDS,
|
|
)
|
|
):
|
|
if (
|
|
SUPPORTED_QUANTS[quant].kind
|
|
not in SUPPORTED_MODELS[MODEL_PRESETS[model]["model_type"]].quantize
|
|
):
|
|
continue
|
|
if not target.startswith("cuda") and quant == "q4f16_ft":
|
|
# FasterTransformer only works with cuda
|
|
continue
|
|
if "deepseek_v2" in model and "32" in quant:
|
|
# Skip f32 for deepseek v2 model for now.
|
|
continue
|
|
log_file = os.path.join(tmp_dir, f"lib{idx}.log")
|
|
cmd = [
|
|
sys.executable,
|
|
"-m",
|
|
"mlc_llm",
|
|
"compile",
|
|
model,
|
|
"--quantization",
|
|
quant,
|
|
"--overrides",
|
|
f"tensor_parallel_shards={tp_shard}",
|
|
"--device",
|
|
target,
|
|
"--opt",
|
|
OPT_LEVEL,
|
|
"-o",
|
|
os.path.join(tmp_dir, f"lib{idx}.{suffix}"),
|
|
]
|
|
future = executor.submit(run_command, log_file, cmd)
|
|
log_files.append(log_file)
|
|
cmds.append(cmd)
|
|
futures.append(future)
|
|
for log_file, cmd, future in zip(log_files, cmds, futures):
|
|
cmd = shlex.join(cmd)
|
|
try:
|
|
future.result()
|
|
passed_cmds.append(cmd)
|
|
print(f"[PASS] {cmd}")
|
|
except Exception:
|
|
failed_cmds.append(cmd)
|
|
print("-------------------------------")
|
|
print(f"[FAIL] {cmd}")
|
|
with open(log_file, encoding="utf-8") as file:
|
|
print(file.read())
|
|
print("-------------------------------")
|
|
print("-------------------------------")
|
|
print(f"Total {len(passed_cmds)} passed, {len(failed_cmds)} failed.")
|
|
print("-------------------------------")
|
|
print("Passed commands:")
|
|
for cmd in passed_cmds:
|
|
print(cmd)
|
|
if failed_cmds:
|
|
print("-------------------------------")
|
|
print("Failed commands:")
|
|
for cmd in failed_cmds:
|
|
print(cmd)
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_model_compile()
|