Compare commits
179 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7193774b1f | ||
|
|
e2c6e0a829 | ||
|
|
770ec6024f | ||
|
|
4f1ba0844b | ||
|
|
873edda6cf | ||
|
|
64840dfae4 | ||
|
|
28e1299e60 | ||
|
|
0c4d2ad5e6 | ||
|
|
c6f2485c82 | ||
|
|
300da09177 | ||
|
|
1c046447a6 | ||
|
|
8fae5ed7f6 | ||
|
|
3368c3ab36 | ||
|
|
1ac3de09cd | ||
|
|
3e073e66f1 | ||
|
|
c23953675f | ||
|
|
e3dd0692fa | ||
|
|
fc3afc20df | ||
|
|
b4522474a3 | ||
|
|
ee777d9c30 | ||
|
|
6e0c9d6bd0 | ||
|
|
6da1ab6b41 | ||
|
|
01b6f9e1f0 | ||
|
|
13f9f7a3d0 | ||
|
|
1e7d5c01f5 | ||
|
|
2467b642dd | ||
|
|
72fc97a0f1 | ||
|
|
2529d09b5a | ||
|
|
a928ded995 | ||
|
|
cc4325b66a | ||
|
|
8ff7ced996 | ||
|
|
3f06bae907 | ||
|
|
b8747e8a7c | ||
|
|
3185fb0cca | ||
|
|
0250dd68c5 | ||
|
|
88577ac928 | ||
|
|
530821d00c | ||
|
|
1a2aef3e59 | ||
|
|
5f7bb58427 | ||
|
|
b05f5c9238 | ||
|
|
9b0e3ec970 | ||
|
|
86e9c8df29 | ||
|
|
ee5f34b1c2 | ||
|
|
f2bd246c17 | ||
|
|
a79e522984 | ||
|
|
3e83c12b5c | ||
|
|
e551ca1555 | ||
|
|
9b8c8ba119 | ||
|
|
d23679eb99 | ||
|
|
57a0702e63 | ||
|
|
3dda7c2250 | ||
|
|
92ba7e7477 | ||
|
|
d4a2ac8302 | ||
|
|
c6bd70d772 | ||
|
|
5b59532760 | ||
|
|
ca2b628b3c | ||
|
|
8ca5051b9a | ||
|
|
06ed2815e2 | ||
|
|
0e40ac9b7b | ||
|
|
13d88d4137 | ||
|
|
d66ac62854 | ||
|
|
9dc7c6c7f3 | ||
|
|
ec4aaad812 | ||
|
|
4dfdf43196 | ||
|
|
5e85f4f82a | ||
|
|
71c60491f2 | ||
|
|
0faab90eb0 | ||
|
|
0455c46ed4 | ||
|
|
d4bf085ad0 | ||
|
|
0057894ef7 | ||
|
|
0f961b3ce9 | ||
|
|
7f9c8902e3 | ||
|
|
7c8566aa4f | ||
|
|
b4e4eda92e | ||
|
|
2874bac618 | ||
|
|
035fa895ec | ||
|
|
b28298f2f4 | ||
|
|
2940afa04e | ||
|
|
3b63de9353 | ||
|
|
260d40b5ea | ||
|
|
9e5ec35b1f | ||
|
|
18ae428a0d | ||
|
|
de6f90a13d | ||
|
|
6cb748e190 | ||
|
|
9e99407e3c | ||
|
|
ea4647b7d7 | ||
|
|
e42c634acb | ||
|
|
9cc373f390 | ||
|
|
76515f303b | ||
|
|
855c8ae2c9 | ||
|
|
c52ec5f034 | ||
|
|
02c9afa2d0 | ||
|
|
3118f63385 | ||
|
|
4c34ce8916 | ||
|
|
0d47bf3bf4 | ||
|
|
d9cd78eb71 | ||
|
|
db9120cded | ||
|
|
b3195bc9e4 | ||
|
|
e18749ff09 | ||
|
|
d65798f78c | ||
|
|
a8c1d161a7 | ||
|
|
7c7714d856 | ||
|
|
9d104b5beb | ||
|
|
6ffa3f314c | ||
|
|
e351572900 | ||
|
|
95965d31b6 | ||
|
|
8110e44529 | ||
|
|
09deb4721f | ||
|
|
fa0c114fad | ||
|
|
98f9713399 | ||
|
|
56c3de018c | ||
|
|
a54ed80249 | ||
|
|
9855b99502 | ||
|
|
1009e93c5d | ||
|
|
1b6de8352b | ||
|
|
cbdb252259 | ||
|
|
99aa4eddaf | ||
|
|
ee2bceaaa6 | ||
|
|
1c1bb388e0 | ||
|
|
546034b466 | ||
|
|
cca61642e0 | ||
|
|
5ce45eb54d | ||
|
|
5478c4b41f | ||
|
|
47f5e03b5b | ||
|
|
2759a43a26 | ||
|
|
5d73ae49d6 | ||
|
|
781e3b9a42 | ||
|
|
acd5511b6d | ||
|
|
837c1968f9 | ||
|
|
a091e2da3e | ||
|
|
fc990f9795 | ||
|
|
3724d5f6b5 | ||
|
|
50e9ec41fc | ||
|
|
47790f3e32 | ||
|
|
a36e070dad | ||
|
|
8a0cf1ddc3 | ||
|
|
1ef0d2efd0 | ||
|
|
851725202a | ||
|
|
9ba0817ff1 | ||
|
|
18e9e1f7b3 | ||
|
|
f57092c00b | ||
|
|
a84e598e21 | ||
|
|
0a4806f0a9 | ||
|
|
ecd7a1d5b6 | ||
|
|
a2469127db | ||
|
|
06311e2956 | ||
|
|
cab69a15e4 | ||
|
|
9b4a3b235e | ||
|
|
acda0b35d0 | ||
|
|
ba77527955 | ||
|
|
6821020109 | ||
|
|
8427550488 | ||
|
|
3f79bc3d1a | ||
|
|
40c396533d | ||
|
|
5ec9c0fb3c | ||
|
|
8f44a92d85 | ||
|
|
360ddbd37e | ||
|
|
a480939e8e | ||
|
|
d31174a4e1 | ||
|
|
b61bd98f90 | ||
|
|
c16369455f | ||
|
|
019877253b | ||
|
|
551ce01078 | ||
|
|
a6c0f3658d | ||
|
|
f2e263b801 | ||
|
|
1f0c75afa9 | ||
|
|
8a23e93302 | ||
|
|
c6202daeed | ||
|
|
e56bf27741 | ||
|
|
520ca380ae | ||
|
|
7de49aa86c | ||
|
|
42ffba11ad | ||
|
|
295c4730a8 | ||
|
|
1bf2dd9df0 | ||
|
|
5a60699c45 | ||
|
|
b6c75e1cf2 | ||
|
|
b71c956deb | ||
|
|
f842a7aff1 | ||
|
|
a65cb16067 |
@@ -8,8 +8,7 @@ steps:
|
|||||||
containers:
|
containers:
|
||||||
- image: badouralix/curl-jq
|
- image: badouralix/curl-jq
|
||||||
command:
|
command:
|
||||||
- sh
|
- sh .buildkite/nightly-benchmarks/scripts/wait-for-image.sh
|
||||||
- .buildkite/nightly-benchmarks/scripts/wait-for-image.sh
|
|
||||||
- wait
|
- wait
|
||||||
- label: "A100"
|
- label: "A100"
|
||||||
agents:
|
agents:
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
TOKEN=$(curl -s -L "https://public.ecr.aws/token?service=public.ecr.aws&scope=repository:q9t5s3a7/vllm-ci-test-repo:pull" | jq -r .token)
|
TOKEN=$(curl -s -L "https://public.ecr.aws/token?service=public.ecr.aws&scope=repository:q9t5s3a7/vllm-ci-test-repo:pull" | jq -r .token)
|
||||||
URL="https://public.ecr.aws/v2/q9t5s3a7/vllm-ci-test-repo/manifests/$BUILDKITE_COMMIT"
|
URL="https://public.ecr.aws/v2/q9t5s3a7/vllm-ci-test-repo/manifests/$BUILDKITE_COMMIT"
|
||||||
|
|
||||||
|
TIMEOUT_SECONDS=10
|
||||||
|
|
||||||
retries=0
|
retries=0
|
||||||
while [ $retries -lt 1000 ]; do
|
while [ $retries -lt 1000 ]; do
|
||||||
if [ $(curl -s -L -H "Authorization: Bearer $TOKEN" -o /dev/null -w "%{http_code}" $URL) -eq 200 ]; then
|
if [ $(curl -s --max-time $TIMEOUT_SECONDS -L -H "Authorization: Bearer $TOKEN" -o /dev/null -w "%{http_code}" $URL) -eq 200 ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ if [[ $commands == *" kernels "* ]]; then
|
|||||||
--ignore=kernels/test_encoder_decoder_attn.py \
|
--ignore=kernels/test_encoder_decoder_attn.py \
|
||||||
--ignore=kernels/test_flash_attn.py \
|
--ignore=kernels/test_flash_attn.py \
|
||||||
--ignore=kernels/test_flashinfer.py \
|
--ignore=kernels/test_flashinfer.py \
|
||||||
|
--ignore=kernels/test_gguf.py \
|
||||||
--ignore=kernels/test_int8_quant.py \
|
--ignore=kernels/test_int8_quant.py \
|
||||||
--ignore=kernels/test_machete_gemm.py \
|
--ignore=kernels/test_machete_gemm.py \
|
||||||
--ignore=kernels/test_mamba_ssm.py \
|
--ignore=kernels/test_mamba_ssm.py \
|
||||||
@@ -93,6 +94,16 @@ if [[ $commands == *" kernels "* ]]; then
|
|||||||
--ignore=kernels/test_sampler.py"
|
--ignore=kernels/test_sampler.py"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#ignore certain Entrypoints tests
|
||||||
|
if [[ $commands == *" entrypoints/openai "* ]]; then
|
||||||
|
commands=${commands//" entrypoints/openai "/" entrypoints/openai \
|
||||||
|
--ignore=entrypoints/openai/test_accuracy.py \
|
||||||
|
--ignore=entrypoints/openai/test_audio.py \
|
||||||
|
--ignore=entrypoints/openai/test_encoder_decoder.py \
|
||||||
|
--ignore=entrypoints/openai/test_embedding.py \
|
||||||
|
--ignore=entrypoints/openai/test_oot_registration.py "}
|
||||||
|
fi
|
||||||
|
|
||||||
PARALLEL_JOB_COUNT=8
|
PARALLEL_JOB_COUNT=8
|
||||||
# check if the command contains shard flag, we will run all shards in parallel because the host have 8 GPUs.
|
# check if the command contains shard flag, we will run all shards in parallel because the host have 8 GPUs.
|
||||||
if [[ $commands == *"--shard-id="* ]]; then
|
if [[ $commands == *"--shard-id="* ]]; then
|
||||||
|
|||||||
@@ -22,13 +22,11 @@ docker exec cpu-test-avx2 bash -c "python3 examples/offline_inference.py"
|
|||||||
|
|
||||||
# Run basic model test
|
# Run basic model test
|
||||||
docker exec cpu-test bash -c "
|
docker exec cpu-test bash -c "
|
||||||
pip install pytest matplotlib einops transformers_stream_generator
|
pip install pytest matplotlib einops transformers_stream_generator datamodel_code_generator
|
||||||
pytest -v -s tests/models -m \"not vlm\" --ignore=tests/models/test_embedding.py \
|
pytest -v -s tests/models/decoder_only/language \
|
||||||
--ignore=tests/models/test_oot_registration.py \
|
--ignore=tests/models/test_fp8.py \
|
||||||
--ignore=tests/models/test_registry.py \
|
--ignore=tests/models/decoder_only/language/test_jamba.py \
|
||||||
--ignore=tests/models/test_fp8.py \
|
--ignore=tests/models/decoder_only/language/test_danube3_4b.py" # Mamba and Danube3-4B on CPU is not supported
|
||||||
--ignore=tests/models/test_jamba.py \
|
|
||||||
--ignore=tests/models/test_danube3_4b.py" # Mamba and Danube3-4B on CPU is not supported
|
|
||||||
|
|
||||||
# Run compressed-tensor test
|
# Run compressed-tensor test
|
||||||
docker exec cpu-test bash -c "
|
docker exec cpu-test bash -c "
|
||||||
|
|||||||
@@ -43,13 +43,16 @@ steps:
|
|||||||
fast_check: true
|
fast_check: true
|
||||||
source_file_dependencies:
|
source_file_dependencies:
|
||||||
- vllm/
|
- vllm/
|
||||||
|
- tests/mq_llm_engine
|
||||||
- tests/async_engine
|
- tests/async_engine
|
||||||
- tests/test_inputs
|
- tests/test_inputs
|
||||||
- tests/multimodal
|
- tests/multimodal
|
||||||
- tests/test_utils
|
- tests/test_utils
|
||||||
- tests/worker
|
- tests/worker
|
||||||
commands:
|
commands:
|
||||||
- pytest -v -s async_engine # Async Engine
|
- pytest -v -s mq_llm_engine # MQLLMEngine
|
||||||
|
- pytest -v -s async_engine # AsyncLLMEngine
|
||||||
|
- NUM_SCHEDULER_STEPS=4 pytest -v -s async_engine/test_async_llm_engine.py
|
||||||
- pytest -v -s test_inputs.py
|
- pytest -v -s test_inputs.py
|
||||||
- pytest -v -s multimodal
|
- pytest -v -s multimodal
|
||||||
- pytest -v -s test_utils.py # Utils
|
- pytest -v -s test_utils.py # Utils
|
||||||
@@ -67,7 +70,7 @@ steps:
|
|||||||
- VLLM_ATTENTION_BACKEND=XFORMERS pytest -v -s basic_correctness/test_chunked_prefill.py
|
- VLLM_ATTENTION_BACKEND=XFORMERS pytest -v -s basic_correctness/test_chunked_prefill.py
|
||||||
- VLLM_ATTENTION_BACKEND=FLASH_ATTN pytest -v -s basic_correctness/test_chunked_prefill.py
|
- VLLM_ATTENTION_BACKEND=FLASH_ATTN pytest -v -s basic_correctness/test_chunked_prefill.py
|
||||||
- VLLM_TEST_ENABLE_ARTIFICIAL_PREEMPT=1 pytest -v -s basic_correctness/test_preemption.py
|
- VLLM_TEST_ENABLE_ARTIFICIAL_PREEMPT=1 pytest -v -s basic_correctness/test_preemption.py
|
||||||
|
|
||||||
- label: Core Test # 10min
|
- label: Core Test # 10min
|
||||||
mirror_hardwares: [amd]
|
mirror_hardwares: [amd]
|
||||||
fast_check: true
|
fast_check: true
|
||||||
@@ -81,17 +84,20 @@ steps:
|
|||||||
- label: Entrypoints Test # 20min
|
- label: Entrypoints Test # 20min
|
||||||
working_dir: "/vllm-workspace/tests"
|
working_dir: "/vllm-workspace/tests"
|
||||||
fast_check: true
|
fast_check: true
|
||||||
#mirror_hardwares: [amd]
|
mirror_hardwares: [amd]
|
||||||
source_file_dependencies:
|
source_file_dependencies:
|
||||||
- vllm/
|
- vllm/
|
||||||
commands:
|
commands:
|
||||||
- pip install -e ./plugins/vllm_add_dummy_model
|
- pip install -e ./plugins/vllm_add_dummy_model
|
||||||
- pip install git+https://github.com/EleutherAI/lm-evaluation-harness.git@a4987bba6e9e9b3f22bd3a6c1ecf0abd04fd5622#egg=lm_eval[api]
|
- pip install git+https://github.com/EleutherAI/lm-evaluation-harness.git@a4987bba6e9e9b3f22bd3a6c1ecf0abd04fd5622#egg=lm_eval[api]
|
||||||
- pytest -v -s entrypoints/llm --ignore=entrypoints/llm/test_lazy_outlines.py
|
- pytest -v -s entrypoints/llm --ignore=entrypoints/llm/test_lazy_outlines.py --ignore=entrypoints/llm/test_generate.py --ignore=entrypoints/llm/test_generate_multiple_loras.py --ignore=entrypoints/llm/test_guided_generate.py
|
||||||
- pytest -v -s entrypoints/llm/test_lazy_outlines.py # it needs a clean process
|
- pytest -v -s entrypoints/llm/test_lazy_outlines.py # it needs a clean process
|
||||||
|
- pytest -v -s entrypoints/llm/test_generate.py # it needs a clean process
|
||||||
|
- pytest -v -s entrypoints/llm/test_generate_multiple_loras.py # it needs a clean process
|
||||||
|
- pytest -v -s entrypoints/llm/test_guided_generate.py # it needs a clean process
|
||||||
- pytest -v -s entrypoints/openai
|
- pytest -v -s entrypoints/openai
|
||||||
- pytest -v -s entrypoints/test_chat_utils.py
|
- pytest -v -s entrypoints/test_chat_utils.py
|
||||||
|
- pytest -v -s entrypoints/offline_mode # Needs to avoid interference with other tests
|
||||||
|
|
||||||
- label: Distributed Tests (4 GPUs) # 10min
|
- label: Distributed Tests (4 GPUs) # 10min
|
||||||
working_dir: "/vllm-workspace/tests"
|
working_dir: "/vllm-workspace/tests"
|
||||||
@@ -162,30 +168,6 @@ steps:
|
|||||||
- python3 tensorize_vllm_model.py --model facebook/opt-125m serialize --serialized-directory /tmp/ --suffix v1 && python3 tensorize_vllm_model.py --model facebook/opt-125m deserialize --path-to-tensors /tmp/vllm/facebook/opt-125m/v1/model.tensors
|
- python3 tensorize_vllm_model.py --model facebook/opt-125m serialize --serialized-directory /tmp/ --suffix v1 && python3 tensorize_vllm_model.py --model facebook/opt-125m deserialize --path-to-tensors /tmp/vllm/facebook/opt-125m/v1/model.tensors
|
||||||
- python3 offline_inference_encoder_decoder.py
|
- python3 offline_inference_encoder_decoder.py
|
||||||
|
|
||||||
- label: Models Test # 1hr10min
|
|
||||||
source_file_dependencies:
|
|
||||||
- vllm/
|
|
||||||
- tests/models
|
|
||||||
commands:
|
|
||||||
- pip install -e ./plugins/vllm_add_dummy_model
|
|
||||||
- pytest -v -s models/test_oot_registration.py # it needs a clean process
|
|
||||||
- pytest -v -s models -m \"not vlm\" --ignore=models/test_oot_registration.py
|
|
||||||
|
|
||||||
- label: torch compile integration test
|
|
||||||
source_file_dependencies:
|
|
||||||
- vllm/
|
|
||||||
commands:
|
|
||||||
- pytest -v -s ./compile/test_full_graph.py
|
|
||||||
- pytest -v -s ./compile/test_wrapper.py
|
|
||||||
|
|
||||||
|
|
||||||
- label: Vision Language Models Test # 42min
|
|
||||||
#mirror_hardwares: [amd]
|
|
||||||
source_file_dependencies:
|
|
||||||
- vllm/
|
|
||||||
commands:
|
|
||||||
- pytest -v -s models -m vlm
|
|
||||||
|
|
||||||
- label: Prefix Caching Test # 7min
|
- label: Prefix Caching Test # 7min
|
||||||
#mirror_hardwares: [amd]
|
#mirror_hardwares: [amd]
|
||||||
source_file_dependencies:
|
source_file_dependencies:
|
||||||
@@ -228,6 +210,21 @@ steps:
|
|||||||
command: pytest -v -s lora --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT --ignore=lora/test_long_context.py
|
command: pytest -v -s lora --shard-id=$$BUILDKITE_PARALLEL_JOB --num-shards=$$BUILDKITE_PARALLEL_JOB_COUNT --ignore=lora/test_long_context.py
|
||||||
parallelism: 4
|
parallelism: 4
|
||||||
|
|
||||||
|
- label: "PyTorch Fullgraph Smoke Test"
|
||||||
|
fast_check: true
|
||||||
|
source_file_dependencies:
|
||||||
|
- vllm/
|
||||||
|
- tests/compile
|
||||||
|
commands:
|
||||||
|
- pytest -v -s compile/test_full_graph_smoke.py
|
||||||
|
|
||||||
|
- label: "PyTorch Fullgraph Test"
|
||||||
|
source_file_dependencies:
|
||||||
|
- vllm/
|
||||||
|
- tests/compile
|
||||||
|
commands:
|
||||||
|
- pytest -v -s compile/test_full_graph.py
|
||||||
|
|
||||||
- label: Kernels Test %N # 30min each
|
- label: Kernels Test %N # 30min each
|
||||||
mirror_hardwares: [amd]
|
mirror_hardwares: [amd]
|
||||||
source_file_dependencies:
|
source_file_dependencies:
|
||||||
@@ -275,6 +272,13 @@ steps:
|
|||||||
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
|
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
|
||||||
- bash ./run-tests.sh -c configs/models-small.txt -t 1
|
- bash ./run-tests.sh -c configs/models-small.txt -t 1
|
||||||
|
|
||||||
|
- label: Encoder Decoder tests # 5min
|
||||||
|
source_file_dependencies:
|
||||||
|
- vllm/
|
||||||
|
- tests/encoder_decoder
|
||||||
|
commands:
|
||||||
|
- pytest -v -s encoder_decoder
|
||||||
|
|
||||||
- label: OpenAI-Compatible Tool Use # 20 min
|
- label: OpenAI-Compatible Tool Use # 20 min
|
||||||
fast_check: false
|
fast_check: false
|
||||||
mirror_hardwares: [ amd ]
|
mirror_hardwares: [ amd ]
|
||||||
@@ -284,6 +288,45 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- pytest -v -s tool_use
|
- pytest -v -s tool_use
|
||||||
|
|
||||||
|
##### models test #####
|
||||||
|
|
||||||
|
- label: Basic Models Test # 3min
|
||||||
|
source_file_dependencies:
|
||||||
|
- vllm/
|
||||||
|
- tests/models
|
||||||
|
commands:
|
||||||
|
- pip install -e ./plugins/vllm_add_dummy_model
|
||||||
|
- pytest -v -s models/test_oot_registration.py # it needs a clean process
|
||||||
|
- pytest -v -s models/*.py --ignore=models/test_oot_registration.py
|
||||||
|
|
||||||
|
- label: Decoder-only Language Models Test # 1h3min
|
||||||
|
#mirror_hardwares: [amd]
|
||||||
|
source_file_dependencies:
|
||||||
|
- vllm/
|
||||||
|
- tests/models/decoder_only/language
|
||||||
|
commands:
|
||||||
|
- pytest -v -s models/decoder_only/language
|
||||||
|
|
||||||
|
- label: Decoder-only Multi-Modal Models Test # 56min
|
||||||
|
#mirror_hardwares: [amd]
|
||||||
|
source_file_dependencies:
|
||||||
|
- vllm/
|
||||||
|
- tests/models/decoder_only/audio_language
|
||||||
|
- tests/models/decoder_only/vision_language
|
||||||
|
commands:
|
||||||
|
- pytest -v -s models/decoder_only/audio_language
|
||||||
|
- pytest -v -s models/decoder_only/vision_language
|
||||||
|
|
||||||
|
- label: Other Models Test # 5min
|
||||||
|
#mirror_hardwares: [amd]
|
||||||
|
source_file_dependencies:
|
||||||
|
- vllm/
|
||||||
|
- tests/models/embedding/language
|
||||||
|
- tests/models/encoder_decoder/language
|
||||||
|
commands:
|
||||||
|
- pytest -v -s models/embedding/language
|
||||||
|
- pytest -v -s models/encoder_decoder/language
|
||||||
|
|
||||||
##### 1 GPU test #####
|
##### 1 GPU test #####
|
||||||
##### multi gpus test #####
|
##### multi gpus test #####
|
||||||
|
|
||||||
@@ -309,11 +352,11 @@ steps:
|
|||||||
- tests/distributed/
|
- tests/distributed/
|
||||||
commands:
|
commands:
|
||||||
- # the following commands are for the first node, with ip 192.168.10.10 (ray environment already set up)
|
- # the following commands are for the first node, with ip 192.168.10.10 (ray environment already set up)
|
||||||
- VLLM_TEST_SAME_HOST=0 torchrun --nnodes 2 --nproc-per-node=2 --rdzv_backend=c10d --rdzv_endpoint=192.168.10.10 distributed/test_same_node.py
|
- VLLM_TEST_SAME_HOST=0 torchrun --nnodes 2 --nproc-per-node=2 --rdzv_backend=c10d --rdzv_endpoint=192.168.10.10 distributed/test_same_node.py | grep -q 'Same node test passed'
|
||||||
- VLLM_MULTI_NODE=1 pytest -v -s distributed/test_multi_node_assignment.py
|
- VLLM_MULTI_NODE=1 pytest -v -s distributed/test_multi_node_assignment.py
|
||||||
- VLLM_MULTI_NODE=1 pytest -v -s distributed/test_pipeline_parallel.py
|
- VLLM_MULTI_NODE=1 pytest -v -s distributed/test_pipeline_parallel.py
|
||||||
- # the following commands are for the second node, with ip 192.168.10.11 (ray environment already set up)
|
- # the following commands are for the second node, with ip 192.168.10.11 (ray environment already set up)
|
||||||
- VLLM_TEST_SAME_HOST=0 torchrun --nnodes 2 --nproc-per-node=2 --rdzv_backend=c10d --rdzv_endpoint=192.168.10.10 distributed/test_same_node.py
|
- VLLM_TEST_SAME_HOST=0 torchrun --nnodes 2 --nproc-per-node=2 --rdzv_backend=c10d --rdzv_endpoint=192.168.10.10 distributed/test_same_node.py | grep -q 'Same node test passed'
|
||||||
|
|
||||||
- label: Distributed Tests (2 GPUs) # 28min
|
- label: Distributed Tests (2 GPUs) # 28min
|
||||||
#mirror_hardwares: [amd]
|
#mirror_hardwares: [amd]
|
||||||
@@ -325,12 +368,14 @@ steps:
|
|||||||
- vllm/executor/
|
- vllm/executor/
|
||||||
- vllm/model_executor/models/
|
- vllm/model_executor/models/
|
||||||
- tests/distributed/
|
- tests/distributed/
|
||||||
|
- vllm/compilation
|
||||||
commands:
|
commands:
|
||||||
- VLLM_TEST_SAME_HOST=1 torchrun --nproc-per-node=4 distributed/test_same_node.py
|
- pytest -v -s ./compile/test_full_graph_multi_gpu.py
|
||||||
- TARGET_TEST_SUITE=L4 pytest -v -s distributed/test_basic_distributed_correctness.py
|
- pytest -v -s ./compile/test_wrapper.py
|
||||||
- pytest -v -s distributed/test_basic_distributed_correctness_enc_dec.py
|
- VLLM_TEST_SAME_HOST=1 torchrun --nproc-per-node=4 distributed/test_same_node.py | grep -q 'Same node test passed'
|
||||||
- pytest -v -s distributed/test_chunked_prefill_distributed.py
|
- TARGET_TEST_SUITE=L4 pytest basic_correctness/ -v -s -m distributed_2_gpus
|
||||||
- pytest -v -s distributed/test_multimodal_broadcast.py
|
# Avoid importing model tests that cause CUDA reinitialization error
|
||||||
|
- pytest models/encoder_decoder/language/test_bart.py models/decoder_only/vision_language/test_broadcast.py -v -s -m distributed_2_gpus
|
||||||
- pytest -v -s spec_decode/e2e/test_integration_dist_tp2.py
|
- pytest -v -s spec_decode/e2e/test_integration_dist_tp2.py
|
||||||
- pip install -e ./plugins/vllm_add_dummy_model
|
- pip install -e ./plugins/vllm_add_dummy_model
|
||||||
- pytest -v -s distributed/test_distributed_oot.py
|
- pytest -v -s distributed/test_distributed_oot.py
|
||||||
|
|||||||
9
.github/ISSUE_TEMPLATE/400-bug report.yml
vendored
9
.github/ISSUE_TEMPLATE/400-bug report.yml
vendored
@@ -30,6 +30,15 @@ body:
|
|||||||
</details>
|
</details>
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Model Input Dumps
|
||||||
|
description: |
|
||||||
|
If you are facing crashing due to illegal memory access or other issues with model execution, vLLM may dump the problematic input of the model. In this case, you will see the message `Error in model execution (input dumped to /tmp/err_xxx.pkl)`. If you see this message, please zip the file (because GitHub doesn't support .pkl file format) and upload it here. This will help us to reproduce the issue and facilitate the debugging process.
|
||||||
|
placeholder: |
|
||||||
|
Upload the dumped input file.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 🐛 Describe the bug
|
label: 🐛 Describe the bug
|
||||||
|
|||||||
4
.github/workflows/ruff.yml
vendored
4
.github/workflows/ruff.yml
vendored
@@ -25,10 +25,10 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install ruff==0.1.5 codespell==2.3.0 tomli==2.0.1 isort==5.13.2
|
pip install -r requirements-lint.txt
|
||||||
- name: Analysing the code with ruff
|
- name: Analysing the code with ruff
|
||||||
run: |
|
run: |
|
||||||
ruff .
|
ruff check .
|
||||||
- name: Spelling check with codespell
|
- name: Spelling check with codespell
|
||||||
run: |
|
run: |
|
||||||
codespell --toml pyproject.toml
|
codespell --toml pyproject.toml
|
||||||
|
|||||||
1
.github/workflows/scripts/build.sh
vendored
1
.github/workflows/scripts/build.sh
vendored
@@ -15,5 +15,6 @@ $python_executable -m pip install -r requirements-cuda.txt
|
|||||||
export MAX_JOBS=1
|
export MAX_JOBS=1
|
||||||
# Make sure release wheels are built for the following architectures
|
# Make sure release wheels are built for the following architectures
|
||||||
export TORCH_CUDA_ARCH_LIST="7.0 7.5 8.0 8.6 8.9 9.0+PTX"
|
export TORCH_CUDA_ARCH_LIST="7.0 7.5 8.0 8.6 8.9 9.0+PTX"
|
||||||
|
export VLLM_FA_CMAKE_GPU_ARCHES="80-real;90-real"
|
||||||
# Build
|
# Build
|
||||||
$python_executable setup.py bdist_wheel --dist-dir=dist
|
$python_executable setup.py bdist_wheel --dist-dir=dist
|
||||||
|
|||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,5 +1,8 @@
|
|||||||
# vllm commit id, generated by setup.py
|
# version file generated by setuptools-scm
|
||||||
vllm/commit_id.py
|
/vllm/_version.py
|
||||||
|
|
||||||
|
# vllm-flash-attn built from source
|
||||||
|
vllm/vllm_flash_attn/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@@ -12,6 +15,8 @@ __pycache__/
|
|||||||
# Distribution / packaging
|
# Distribution / packaging
|
||||||
.Python
|
.Python
|
||||||
build/
|
build/
|
||||||
|
cmake-build-*/
|
||||||
|
CMakeUserPresets.json
|
||||||
develop-eggs/
|
develop-eggs/
|
||||||
dist/
|
dist/
|
||||||
downloads/
|
downloads/
|
||||||
|
|||||||
132
CMakeLists.txt
132
CMakeLists.txt
@@ -1,5 +1,16 @@
|
|||||||
cmake_minimum_required(VERSION 3.26)
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
|
# When building directly using CMake, make sure you run the install step
|
||||||
|
# (it places the .so files in the correct location).
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# mkdir build && cd build
|
||||||
|
# cmake -G Ninja -DVLLM_PYTHON_EXECUTABLE=`which python3` -DCMAKE_INSTALL_PREFIX=.. ..
|
||||||
|
# cmake --build . --target install
|
||||||
|
#
|
||||||
|
# If you want to only build one target, make sure to install it manually:
|
||||||
|
# cmake --build . --target _C
|
||||||
|
# cmake --install . --component _C
|
||||||
project(vllm_extensions LANGUAGES CXX)
|
project(vllm_extensions LANGUAGES CXX)
|
||||||
|
|
||||||
# CUDA by default, can be overridden by using -DVLLM_TARGET_DEVICE=... (used by setup.py)
|
# CUDA by default, can be overridden by using -DVLLM_TARGET_DEVICE=... (used by setup.py)
|
||||||
@@ -13,6 +24,9 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/utils.cmake)
|
|||||||
# Suppress potential warnings about unused manually-specified variables
|
# Suppress potential warnings about unused manually-specified variables
|
||||||
set(ignoreMe "${VLLM_PYTHON_PATH}")
|
set(ignoreMe "${VLLM_PYTHON_PATH}")
|
||||||
|
|
||||||
|
# Prevent installation of dependencies (cutlass) by default.
|
||||||
|
install(CODE "set(CMAKE_INSTALL_LOCAL_ONLY TRUE)" ALL_COMPONENTS)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Supported python versions. These versions will be searched in order, the
|
# Supported python versions. These versions will be searched in order, the
|
||||||
# first match will be selected. These should be kept in sync with setup.py.
|
# first match will be selected. These should be kept in sync with setup.py.
|
||||||
@@ -70,19 +84,6 @@ endif()
|
|||||||
find_package(Torch REQUIRED)
|
find_package(Torch REQUIRED)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Add the `default` target which detects which extensions should be
|
|
||||||
# built based on platform/architecture. This is the same logic that
|
|
||||||
# setup.py uses to select which extensions should be built and should
|
|
||||||
# be kept in sync.
|
|
||||||
#
|
|
||||||
# The `default` target makes direct use of cmake easier since knowledge
|
|
||||||
# of which extensions are supported has been factored in, e.g.
|
|
||||||
#
|
|
||||||
# mkdir build && cd build
|
|
||||||
# cmake -G Ninja -DVLLM_PYTHON_EXECUTABLE=`which python3` -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=../vllm ..
|
|
||||||
# cmake --build . --target default
|
|
||||||
#
|
|
||||||
add_custom_target(default)
|
|
||||||
message(STATUS "Enabling core extension.")
|
message(STATUS "Enabling core extension.")
|
||||||
|
|
||||||
# Define _core_C extension
|
# Define _core_C extension
|
||||||
@@ -100,8 +101,6 @@ define_gpu_extension_target(
|
|||||||
USE_SABI 3
|
USE_SABI 3
|
||||||
WITH_SOABI)
|
WITH_SOABI)
|
||||||
|
|
||||||
add_dependencies(default _core_C)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Forward the non-CUDA device extensions to external CMake scripts.
|
# Forward the non-CUDA device extensions to external CMake scripts.
|
||||||
#
|
#
|
||||||
@@ -167,6 +166,8 @@ if(NVCC_THREADS AND VLLM_GPU_LANG STREQUAL "CUDA")
|
|||||||
list(APPEND VLLM_GPU_FLAGS "--threads=${NVCC_THREADS}")
|
list(APPEND VLLM_GPU_FLAGS "--threads=${NVCC_THREADS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Define other extension targets
|
# Define other extension targets
|
||||||
#
|
#
|
||||||
@@ -190,8 +191,11 @@ set(VLLM_EXT_SRC
|
|||||||
"csrc/torch_bindings.cpp")
|
"csrc/torch_bindings.cpp")
|
||||||
|
|
||||||
if(VLLM_GPU_LANG STREQUAL "CUDA")
|
if(VLLM_GPU_LANG STREQUAL "CUDA")
|
||||||
include(FetchContent)
|
|
||||||
SET(CUTLASS_ENABLE_HEADERS_ONLY ON CACHE BOOL "Enable only the header library")
|
SET(CUTLASS_ENABLE_HEADERS_ONLY ON CACHE BOOL "Enable only the header library")
|
||||||
|
|
||||||
|
# Set CUTLASS_REVISION manually -- its revision detection doesn't work in this case.
|
||||||
|
set(CUTLASS_REVISION "v3.5.1" CACHE STRING "CUTLASS revision to use")
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
cutlass
|
cutlass
|
||||||
GIT_REPOSITORY https://github.com/nvidia/cutlass.git
|
GIT_REPOSITORY https://github.com/nvidia/cutlass.git
|
||||||
@@ -219,6 +223,7 @@ if(VLLM_GPU_LANG STREQUAL "CUDA")
|
|||||||
"csrc/quantization/gguf/gguf_kernel.cu"
|
"csrc/quantization/gguf/gguf_kernel.cu"
|
||||||
"csrc/quantization/fp8/fp8_marlin.cu"
|
"csrc/quantization/fp8/fp8_marlin.cu"
|
||||||
"csrc/custom_all_reduce.cu"
|
"csrc/custom_all_reduce.cu"
|
||||||
|
"csrc/permute_cols.cu"
|
||||||
"csrc/quantization/cutlass_w8a8/scaled_mm_entry.cu"
|
"csrc/quantization/cutlass_w8a8/scaled_mm_entry.cu"
|
||||||
"csrc/quantization/cutlass_w8a8/scaled_mm_c2x.cu"
|
"csrc/quantization/cutlass_w8a8/scaled_mm_c2x.cu"
|
||||||
"csrc/quantization/cutlass_w8a8/scaled_mm_c3x.cu")
|
"csrc/quantization/cutlass_w8a8/scaled_mm_c3x.cu")
|
||||||
@@ -283,6 +288,7 @@ if(VLLM_GPU_LANG STREQUAL "CUDA")
|
|||||||
csrc/quantization/machete/machete_pytorch.cu)
|
csrc/quantization/machete/machete_pytorch.cu)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Enabling C extension.")
|
||||||
define_gpu_extension_target(
|
define_gpu_extension_target(
|
||||||
_C
|
_C
|
||||||
DESTINATION vllm
|
DESTINATION vllm
|
||||||
@@ -310,9 +316,15 @@ set(VLLM_MOE_EXT_SRC
|
|||||||
|
|
||||||
if(VLLM_GPU_LANG STREQUAL "CUDA")
|
if(VLLM_GPU_LANG STREQUAL "CUDA")
|
||||||
list(APPEND VLLM_MOE_EXT_SRC
|
list(APPEND VLLM_MOE_EXT_SRC
|
||||||
|
"csrc/moe/marlin_kernels/marlin_moe_kernel.h"
|
||||||
|
"csrc/moe/marlin_kernels/marlin_moe_kernel_ku4b8.h"
|
||||||
|
"csrc/moe/marlin_kernels/marlin_moe_kernel_ku4b8.cu"
|
||||||
|
"csrc/moe/marlin_kernels/marlin_moe_kernel_ku8b128.h"
|
||||||
|
"csrc/moe/marlin_kernels/marlin_moe_kernel_ku8b128.cu"
|
||||||
"csrc/moe/marlin_moe_ops.cu")
|
"csrc/moe/marlin_moe_ops.cu")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Enabling moe extension.")
|
||||||
define_gpu_extension_target(
|
define_gpu_extension_target(
|
||||||
_moe_C
|
_moe_C
|
||||||
DESTINATION vllm
|
DESTINATION vllm
|
||||||
@@ -323,13 +335,85 @@ define_gpu_extension_target(
|
|||||||
USE_SABI 3
|
USE_SABI 3
|
||||||
WITH_SOABI)
|
WITH_SOABI)
|
||||||
|
|
||||||
|
if(VLLM_GPU_LANG STREQUAL "HIP")
|
||||||
|
#
|
||||||
|
# _rocm_C extension
|
||||||
|
#
|
||||||
|
set(VLLM_ROCM_EXT_SRC
|
||||||
|
"csrc/rocm/torch_bindings.cpp"
|
||||||
|
"csrc/rocm/attention.cu")
|
||||||
|
|
||||||
|
define_gpu_extension_target(
|
||||||
if(VLLM_GPU_LANG STREQUAL "CUDA" OR VLLM_GPU_LANG STREQUAL "HIP")
|
_rocm_C
|
||||||
message(STATUS "Enabling C extension.")
|
DESTINATION vllm
|
||||||
add_dependencies(default _C)
|
LANGUAGE ${VLLM_GPU_LANG}
|
||||||
|
SOURCES ${VLLM_ROCM_EXT_SRC}
|
||||||
message(STATUS "Enabling moe extension.")
|
COMPILE_FLAGS ${VLLM_GPU_FLAGS}
|
||||||
add_dependencies(default _moe_C)
|
ARCHITECTURES ${VLLM_GPU_ARCHES}
|
||||||
|
USE_SABI 3
|
||||||
|
WITH_SOABI)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# vllm-flash-attn currently only supported on CUDA
|
||||||
|
if (NOT VLLM_TARGET_DEVICE STREQUAL "cuda")
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build vLLM flash attention from source
|
||||||
|
#
|
||||||
|
# IMPORTANT: This has to be the last thing we do, because vllm-flash-attn uses the same macros/functions as vLLM.
|
||||||
|
# Because functions all belong to the global scope, vllm-flash-attn's functions overwrite vLLMs.
|
||||||
|
# They should be identical but if they aren't, this is a massive footgun.
|
||||||
|
#
|
||||||
|
# The vllm-flash-attn install rules are nested under vllm to make sure the library gets installed in the correct place.
|
||||||
|
# To only install vllm-flash-attn, use --component vllm_flash_attn_c.
|
||||||
|
# If no component is specified, vllm-flash-attn is still installed.
|
||||||
|
|
||||||
|
# If VLLM_FLASH_ATTN_SRC_DIR is set, vllm-flash-attn is installed from that directory instead of downloading.
|
||||||
|
# This is to enable local development of vllm-flash-attn within vLLM.
|
||||||
|
# It can be set as an environment variable or passed as a cmake argument.
|
||||||
|
# The environment variable takes precedence.
|
||||||
|
if (DEFINED ENV{VLLM_FLASH_ATTN_SRC_DIR})
|
||||||
|
set(VLLM_FLASH_ATTN_SRC_DIR $ENV{VLLM_FLASH_ATTN_SRC_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(VLLM_FLASH_ATTN_SRC_DIR)
|
||||||
|
FetchContent_Declare(vllm-flash-attn SOURCE_DIR ${VLLM_FLASH_ATTN_SRC_DIR})
|
||||||
|
else()
|
||||||
|
FetchContent_Declare(
|
||||||
|
vllm-flash-attn
|
||||||
|
GIT_REPOSITORY https://github.com/vllm-project/flash-attention.git
|
||||||
|
GIT_TAG 013f0c4fc47e6574060879d9734c1df8c5c273bd
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Set the parent build flag so that the vllm-flash-attn library does not redo compile flag and arch initialization.
|
||||||
|
set(VLLM_PARENT_BUILD ON)
|
||||||
|
|
||||||
|
# Ensure the vllm/vllm_flash_attn directory exists before installation
|
||||||
|
install(CODE "file(MAKE_DIRECTORY \"\${CMAKE_INSTALL_PREFIX}/vllm/vllm_flash_attn\")" COMPONENT vllm_flash_attn_c)
|
||||||
|
|
||||||
|
# Make sure vllm-flash-attn install rules are nested under vllm/
|
||||||
|
install(CODE "set(CMAKE_INSTALL_LOCAL_ONLY FALSE)" COMPONENT vllm_flash_attn_c)
|
||||||
|
install(CODE "set(OLD_CMAKE_INSTALL_PREFIX \"\${CMAKE_INSTALL_PREFIX}\")" COMPONENT vllm_flash_attn_c)
|
||||||
|
install(CODE "set(CMAKE_INSTALL_PREFIX \"\${CMAKE_INSTALL_PREFIX}/vllm/\")" COMPONENT vllm_flash_attn_c)
|
||||||
|
|
||||||
|
# Fetch the vllm-flash-attn library
|
||||||
|
FetchContent_MakeAvailable(vllm-flash-attn)
|
||||||
|
message(STATUS "vllm-flash-attn is available at ${vllm-flash-attn_SOURCE_DIR}")
|
||||||
|
|
||||||
|
# Restore the install prefix
|
||||||
|
install(CODE "set(CMAKE_INSTALL_PREFIX \"\${OLD_CMAKE_INSTALL_PREFIX}\")" COMPONENT vllm_flash_attn_c)
|
||||||
|
install(CODE "set(CMAKE_INSTALL_LOCAL_ONLY TRUE)" COMPONENT vllm_flash_attn_c)
|
||||||
|
|
||||||
|
# Copy over the vllm-flash-attn python files
|
||||||
|
install(
|
||||||
|
DIRECTORY ${vllm-flash-attn_SOURCE_DIR}/vllm_flash_attn/
|
||||||
|
DESTINATION vllm/vllm_flash_attn
|
||||||
|
COMPONENT vllm_flash_attn_c
|
||||||
|
FILES_MATCHING PATTERN "*.py"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Nothing after vllm-flash-attn, see comment about macros above
|
||||||
|
|||||||
16
Dockerfile
16
Dockerfile
@@ -48,6 +48,9 @@ RUN --mount=type=cache,target=/root/.cache/pip \
|
|||||||
# see https://github.com/pytorch/pytorch/pull/123243
|
# see https://github.com/pytorch/pytorch/pull/123243
|
||||||
ARG torch_cuda_arch_list='7.0 7.5 8.0 8.6 8.9 9.0+PTX'
|
ARG torch_cuda_arch_list='7.0 7.5 8.0 8.6 8.9 9.0+PTX'
|
||||||
ENV TORCH_CUDA_ARCH_LIST=${torch_cuda_arch_list}
|
ENV TORCH_CUDA_ARCH_LIST=${torch_cuda_arch_list}
|
||||||
|
# Override the arch list for flash-attn to reduce the binary size
|
||||||
|
ARG vllm_fa_cmake_gpu_arches='80-real;90-real'
|
||||||
|
ENV VLLM_FA_CMAKE_GPU_ARCHES=${vllm_fa_cmake_gpu_arches}
|
||||||
#################### BASE BUILD IMAGE ####################
|
#################### BASE BUILD IMAGE ####################
|
||||||
|
|
||||||
#################### WHEEL BUILD IMAGE ####################
|
#################### WHEEL BUILD IMAGE ####################
|
||||||
@@ -76,14 +79,13 @@ ENV MAX_JOBS=${max_jobs}
|
|||||||
ARG nvcc_threads=8
|
ARG nvcc_threads=8
|
||||||
ENV NVCC_THREADS=$nvcc_threads
|
ENV NVCC_THREADS=$nvcc_threads
|
||||||
|
|
||||||
ARG buildkite_commit
|
|
||||||
ENV BUILDKITE_COMMIT=${buildkite_commit}
|
|
||||||
|
|
||||||
ARG USE_SCCACHE
|
ARG USE_SCCACHE
|
||||||
ARG SCCACHE_BUCKET_NAME=vllm-build-sccache
|
ARG SCCACHE_BUCKET_NAME=vllm-build-sccache
|
||||||
ARG SCCACHE_REGION_NAME=us-west-2
|
ARG SCCACHE_REGION_NAME=us-west-2
|
||||||
|
ARG SCCACHE_S3_NO_CREDENTIALS=0
|
||||||
# if USE_SCCACHE is set, use sccache to speed up compilation
|
# if USE_SCCACHE is set, use sccache to speed up compilation
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
--mount=type=bind,source=.git,target=.git \
|
||||||
if [ "$USE_SCCACHE" = "1" ]; then \
|
if [ "$USE_SCCACHE" = "1" ]; then \
|
||||||
echo "Installing sccache..." \
|
echo "Installing sccache..." \
|
||||||
&& curl -L -o sccache.tar.gz https://github.com/mozilla/sccache/releases/download/v0.8.1/sccache-v0.8.1-x86_64-unknown-linux-musl.tar.gz \
|
&& curl -L -o sccache.tar.gz https://github.com/mozilla/sccache/releases/download/v0.8.1/sccache-v0.8.1-x86_64-unknown-linux-musl.tar.gz \
|
||||||
@@ -92,6 +94,7 @@ RUN --mount=type=cache,target=/root/.cache/pip \
|
|||||||
&& rm -rf sccache.tar.gz sccache-v0.8.1-x86_64-unknown-linux-musl \
|
&& rm -rf sccache.tar.gz sccache-v0.8.1-x86_64-unknown-linux-musl \
|
||||||
&& export SCCACHE_BUCKET=${SCCACHE_BUCKET_NAME} \
|
&& export SCCACHE_BUCKET=${SCCACHE_BUCKET_NAME} \
|
||||||
&& export SCCACHE_REGION=${SCCACHE_REGION_NAME} \
|
&& export SCCACHE_REGION=${SCCACHE_REGION_NAME} \
|
||||||
|
&& export SCCACHE_S3_NO_CREDENTIALS=${SCCACHE_S3_NO_CREDENTIALS} \
|
||||||
&& export SCCACHE_IDLE_TIMEOUT=0 \
|
&& export SCCACHE_IDLE_TIMEOUT=0 \
|
||||||
&& export CMAKE_BUILD_TYPE=Release \
|
&& export CMAKE_BUILD_TYPE=Release \
|
||||||
&& sccache --show-stats \
|
&& sccache --show-stats \
|
||||||
@@ -102,6 +105,7 @@ RUN --mount=type=cache,target=/root/.cache/pip \
|
|||||||
ENV CCACHE_DIR=/root/.cache/ccache
|
ENV CCACHE_DIR=/root/.cache/ccache
|
||||||
RUN --mount=type=cache,target=/root/.cache/ccache \
|
RUN --mount=type=cache,target=/root/.cache/ccache \
|
||||||
--mount=type=cache,target=/root/.cache/pip \
|
--mount=type=cache,target=/root/.cache/pip \
|
||||||
|
--mount=type=bind,source=.git,target=.git \
|
||||||
if [ "$USE_SCCACHE" != "1" ]; then \
|
if [ "$USE_SCCACHE" != "1" ]; then \
|
||||||
python3 setup.py bdist_wheel --dist-dir=dist --py-limited-api=cp38; \
|
python3 setup.py bdist_wheel --dist-dir=dist --py-limited-api=cp38; \
|
||||||
fi
|
fi
|
||||||
@@ -180,10 +184,6 @@ FROM vllm-base AS test
|
|||||||
ADD . /vllm-workspace/
|
ADD . /vllm-workspace/
|
||||||
|
|
||||||
# install development dependencies (for testing)
|
# install development dependencies (for testing)
|
||||||
# A newer setuptools is required for installing some test dependencies from source that do not publish python 3.12 wheels
|
|
||||||
# This installation must complete before the test dependencies are collected and installed.
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
||||||
python3 -m pip install "setuptools>=74.1.1"
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
python3 -m pip install -r requirements-dev.txt
|
python3 -m pip install -r requirements-dev.txt
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ FROM vllm-base AS vllm-openai
|
|||||||
|
|
||||||
# install additional dependencies for openai api server
|
# install additional dependencies for openai api server
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
pip install accelerate hf_transfer 'modelscope!=1.15.0'
|
pip install accelerate hf_transfer 'modelscope!=1.15.0' bitsandbytes>=0.44.0 timm==0.9.10
|
||||||
|
|
||||||
ENV VLLM_USAGE_SOURCE production-docker-image
|
ENV VLLM_USAGE_SOURCE production-docker-image
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ RUN echo 'ulimit -c 0' >> ~/.bashrc
|
|||||||
|
|
||||||
RUN pip install https://intel-extension-for-pytorch.s3.amazonaws.com/ipex_dev/cpu/intel_extension_for_pytorch-2.4.0%2Bgitfbaa4bc-cp310-cp310-linux_x86_64.whl
|
RUN pip install https://intel-extension-for-pytorch.s3.amazonaws.com/ipex_dev/cpu/intel_extension_for_pytorch-2.4.0%2Bgitfbaa4bc-cp310-cp310-linux_x86_64.whl
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
ENV PIP_EXTRA_INDEX_URL=https://download.pytorch.org/whl/cpu
|
ENV PIP_EXTRA_INDEX_URL=https://download.pytorch.org/whl/cpu
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
--mount=type=bind,src=requirements-build.txt,target=requirements-build.txt \
|
--mount=type=bind,src=requirements-build.txt,target=requirements-build.txt \
|
||||||
@@ -60,8 +62,10 @@ ENV VLLM_CPU_DISABLE_AVX512=${VLLM_CPU_DISABLE_AVX512}
|
|||||||
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
--mount=type=cache,target=/root/.cache/ccache \
|
--mount=type=cache,target=/root/.cache/ccache \
|
||||||
|
--mount=type=bind,source=.git,target=.git \
|
||||||
VLLM_TARGET_DEVICE=cpu python3 setup.py bdist_wheel && \
|
VLLM_TARGET_DEVICE=cpu python3 setup.py bdist_wheel && \
|
||||||
pip install dist/*.whl
|
pip install dist/*.whl && \
|
||||||
|
rm -rf dist
|
||||||
|
|
||||||
WORKDIR /workspace/
|
WORKDIR /workspace/
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
# default base image
|
# default base image
|
||||||
ARG BASE_IMAGE="public.ecr.aws/neuron/pytorch-inference-neuronx:2.1.2-neuronx-py310-sdk2.19.1-ubuntu20.04"
|
ARG BASE_IMAGE="public.ecr.aws/neuron/pytorch-inference-neuronx:2.1.2-neuronx-py310-sdk2.20.0-ubuntu20.04"
|
||||||
|
|
||||||
FROM $BASE_IMAGE
|
FROM $BASE_IMAGE
|
||||||
|
|
||||||
RUN echo "Base image is $BASE_IMAGE"
|
RUN echo "Base image is $BASE_IMAGE"
|
||||||
|
|
||||||
# Install some basic utilities
|
# Install some basic utilities
|
||||||
RUN apt-get update \
|
RUN apt-get update && \
|
||||||
&& apt-get install python3 python3-pip -y \
|
apt-get install -y \
|
||||||
&& apt-get install -y ffmpeg libsm6 libxext6 libgl1
|
git \
|
||||||
|
python3 \
|
||||||
|
python3-pip \
|
||||||
|
ffmpeg libsm6 libxext6 libgl1
|
||||||
|
|
||||||
### Mount Point ###
|
### Mount Point ###
|
||||||
# When launching the container, mount the code directory to /app
|
# When launching the container, mount the code directory to /app
|
||||||
@@ -20,19 +23,19 @@ RUN python3 -m pip install --upgrade pip
|
|||||||
RUN python3 -m pip install --no-cache-dir fastapi ninja tokenizers pandas
|
RUN python3 -m pip install --no-cache-dir fastapi ninja tokenizers pandas
|
||||||
RUN python3 -m pip install sentencepiece transformers==4.36.2 -U
|
RUN python3 -m pip install sentencepiece transformers==4.36.2 -U
|
||||||
RUN python3 -m pip install transformers-neuronx --extra-index-url=https://pip.repos.neuron.amazonaws.com -U
|
RUN python3 -m pip install transformers-neuronx --extra-index-url=https://pip.repos.neuron.amazonaws.com -U
|
||||||
RUN python3 -m pip install --pre neuronx-cc==2.12.* --extra-index-url=https://pip.repos.neuron.amazonaws.com -U
|
RUN python3 -m pip install --pre neuronx-cc==2.15.* --extra-index-url=https://pip.repos.neuron.amazonaws.com -U
|
||||||
|
|
||||||
COPY ./vllm /app/vllm/vllm
|
COPY . /app/vllm
|
||||||
COPY ./setup.py /app/vllm/setup.py
|
|
||||||
COPY ./requirements-common.txt /app/vllm/requirements-common.txt
|
|
||||||
COPY ./requirements-neuron.txt /app/vllm/requirements-neuron.txt
|
|
||||||
|
|
||||||
RUN cd /app/vllm \
|
RUN cd /app/vllm \
|
||||||
&& python3 -m pip install -U -r requirements-neuron.txt
|
&& python3 -m pip install -U \
|
||||||
|
cmake>=3.26 ninja packaging setuptools-scm>=8 wheel jinja2 \
|
||||||
|
-r requirements-neuron.txt
|
||||||
|
|
||||||
ENV VLLM_TARGET_DEVICE neuron
|
ENV VLLM_TARGET_DEVICE neuron
|
||||||
RUN cd /app/vllm \
|
RUN --mount=type=bind,source=.git,target=.git \
|
||||||
&& pip install -e . \
|
cd /app/vllm \
|
||||||
|
&& pip install --no-build-isolation -v -e . \
|
||||||
&& cd ..
|
&& cd ..
|
||||||
|
|
||||||
CMD ["/bin/bash"]
|
CMD ["/bin/bash"]
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
FROM ubuntu:22.04 AS dev
|
FROM ubuntu:22.04 AS dev
|
||||||
|
|
||||||
RUN apt-get update -y && \
|
RUN apt-get update -y && \
|
||||||
apt-get install -y python3-pip git && \
|
apt-get install -y \
|
||||||
apt-get install -y ffmpeg libsm6 libxext6 libgl1
|
git python3-pip \
|
||||||
|
ffmpeg libsm6 libxext6 libgl1
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
|
||||||
# copy requirements
|
# copy requirements
|
||||||
|
|||||||
@@ -16,9 +16,15 @@ COPY ./ /workspace/vllm
|
|||||||
WORKDIR /workspace/vllm
|
WORKDIR /workspace/vllm
|
||||||
|
|
||||||
# These packages will be in rocketce eventually
|
# These packages will be in rocketce eventually
|
||||||
RUN pip install -v cmake xformers torch==2.3.1 uvloop==0.20.0 -r requirements-cpu.txt --prefer-binary --extra-index-url https://repo.fury.io/mgiessing
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
pip install -v --prefer-binary --extra-index-url https://repo.fury.io/mgiessing \
|
||||||
|
cmake>=3.26 ninja packaging setuptools-scm>=8 wheel jinja2 \
|
||||||
|
torch==2.3.1 \
|
||||||
|
-r requirements-cpu.txt \
|
||||||
|
xformers uvloop==0.20.0
|
||||||
|
|
||||||
RUN VLLM_TARGET_DEVICE=cpu python3 setup.py install
|
RUN --mount=type=bind,source=.git,target=.git \
|
||||||
|
VLLM_TARGET_DEVICE=cpu python3 setup.py install
|
||||||
|
|
||||||
WORKDIR /workspace/
|
WORKDIR /workspace/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Default ROCm 6.1 base image
|
# Default ROCm 6.2 base image
|
||||||
ARG BASE_IMAGE="rocm/pytorch:rocm6.1.2_ubuntu20.04_py3.9_pytorch_staging"
|
ARG BASE_IMAGE="rocm/pytorch:rocm6.2_ubuntu20.04_py3.9_pytorch_release_2.3.0"
|
||||||
|
|
||||||
# Default ROCm ARCHes to build vLLM for.
|
# Default ROCm ARCHes to build vLLM for.
|
||||||
ARG PYTORCH_ROCM_ARCH="gfx908;gfx90a;gfx942;gfx1100"
|
ARG PYTORCH_ROCM_ARCH="gfx908;gfx90a;gfx942;gfx1100"
|
||||||
@@ -7,18 +7,12 @@ ARG PYTORCH_ROCM_ARCH="gfx908;gfx90a;gfx942;gfx1100"
|
|||||||
# Whether to install CK-based flash-attention
|
# Whether to install CK-based flash-attention
|
||||||
# If 0, will not install flash-attention
|
# If 0, will not install flash-attention
|
||||||
ARG BUILD_FA="1"
|
ARG BUILD_FA="1"
|
||||||
# If `TRY_FA_WHEEL=1`, we will try installing flash-attention from `FA_WHEEL_URL`
|
|
||||||
# If this succeeds, we use the downloaded wheel and skip building flash-attention.
|
|
||||||
# Otherwise, ROCm flash-attention from `FA_BRANCH` will be built for the
|
|
||||||
# architectures specified in `FA_GFX_ARCHS`
|
|
||||||
ARG TRY_FA_WHEEL="1"
|
|
||||||
ARG FA_WHEEL_URL="https://github.com/ROCm/flash-attention/releases/download/v2.5.9post1-cktile-vllm/flash_attn-2.5.9.post1-cp39-cp39-linux_x86_64.whl"
|
|
||||||
ARG FA_GFX_ARCHS="gfx90a;gfx942"
|
ARG FA_GFX_ARCHS="gfx90a;gfx942"
|
||||||
ARG FA_BRANCH="23a2b1c2"
|
ARG FA_BRANCH="3cea2fb"
|
||||||
|
|
||||||
# Whether to build triton on rocm
|
# Whether to build triton on rocm
|
||||||
ARG BUILD_TRITON="1"
|
ARG BUILD_TRITON="1"
|
||||||
ARG TRITON_BRANCH="e0fc12c"
|
ARG TRITON_BRANCH="e192dba"
|
||||||
|
|
||||||
### Base image build stage
|
### Base image build stage
|
||||||
FROM $BASE_IMAGE AS base
|
FROM $BASE_IMAGE AS base
|
||||||
@@ -50,14 +44,17 @@ RUN python3 -m pip install --upgrade pip
|
|||||||
# Remove sccache so it doesn't interfere with ccache
|
# Remove sccache so it doesn't interfere with ccache
|
||||||
# TODO: implement sccache support across components
|
# TODO: implement sccache support across components
|
||||||
RUN apt-get purge -y sccache; python3 -m pip uninstall -y sccache; rm -f "$(which sccache)"
|
RUN apt-get purge -y sccache; python3 -m pip uninstall -y sccache; rm -f "$(which sccache)"
|
||||||
# Install torch == 2.5.0 on ROCm
|
|
||||||
RUN case "$(ls /opt | grep -Po 'rocm-[0-9]\.[0-9]')" in \
|
# Install torch == 2.6.0 on ROCm
|
||||||
*"rocm-6.1"*) \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
case "$(ls /opt | grep -Po 'rocm-[0-9]\.[0-9]')" in \
|
||||||
|
*"rocm-6.2"*) \
|
||||||
python3 -m pip uninstall -y torch torchvision \
|
python3 -m pip uninstall -y torch torchvision \
|
||||||
&& python3 -m pip install --no-cache-dir --pre \
|
&& python3 -m pip install --pre \
|
||||||
torch==2.5.0.dev20240726 \
|
torch==2.6.0.dev20240918 \
|
||||||
torchvision==0.20.0.dev20240726 \
|
setuptools-scm>=8 \
|
||||||
--index-url https://download.pytorch.org/whl/nightly/rocm6.1;; \
|
torchvision==0.20.0.dev20240918 \
|
||||||
|
--extra-index-url https://download.pytorch.org/whl/nightly/rocm6.2;; \
|
||||||
*) ;; esac
|
*) ;; esac
|
||||||
|
|
||||||
ENV LLVM_SYMBOLIZER_PATH=/opt/rocm/llvm/bin/llvm-symbolizer
|
ENV LLVM_SYMBOLIZER_PATH=/opt/rocm/llvm/bin/llvm-symbolizer
|
||||||
@@ -79,25 +76,18 @@ RUN cd /opt/rocm/share/amd_smi \
|
|||||||
### Flash-Attention wheel build stage
|
### Flash-Attention wheel build stage
|
||||||
FROM base AS build_fa
|
FROM base AS build_fa
|
||||||
ARG BUILD_FA
|
ARG BUILD_FA
|
||||||
ARG TRY_FA_WHEEL
|
|
||||||
ARG FA_WHEEL_URL
|
|
||||||
ARG FA_GFX_ARCHS
|
ARG FA_GFX_ARCHS
|
||||||
ARG FA_BRANCH
|
ARG FA_BRANCH
|
||||||
# Build ROCm flash-attention wheel if `BUILD_FA = 1`
|
# Build ROCm flash-attention wheel if `BUILD_FA = 1`
|
||||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||||
if [ "$BUILD_FA" = "1" ]; then \
|
if [ "$BUILD_FA" = "1" ]; then \
|
||||||
if [ "${TRY_FA_WHEEL}" = "1" ] && python3 -m pip install "${FA_WHEEL_URL}"; then \
|
mkdir -p libs \
|
||||||
# If a suitable wheel exists, we download it instead of building FA
|
&& cd libs \
|
||||||
mkdir -p /install && wget -N "${FA_WHEEL_URL}" -P /install; \
|
&& git clone https://github.com/ROCm/flash-attention.git \
|
||||||
else \
|
&& cd flash-attention \
|
||||||
mkdir -p libs \
|
&& git checkout "${FA_BRANCH}" \
|
||||||
&& cd libs \
|
&& git submodule update --init \
|
||||||
&& git clone https://github.com/ROCm/flash-attention.git \
|
&& GPU_ARCHS="${FA_GFX_ARCHS}" python3 setup.py bdist_wheel --dist-dir=/install; \
|
||||||
&& cd flash-attention \
|
|
||||||
&& git checkout "${FA_BRANCH}" \
|
|
||||||
&& git submodule update --init \
|
|
||||||
&& GPU_ARCHS="${FA_GFX_ARCHS}" python3 setup.py bdist_wheel --dist-dir=/install; \
|
|
||||||
fi; \
|
|
||||||
# Create an empty directory otherwise as later build stages expect one
|
# Create an empty directory otherwise as later build stages expect one
|
||||||
else mkdir -p /install; \
|
else mkdir -p /install; \
|
||||||
fi
|
fi
|
||||||
@@ -112,6 +102,7 @@ RUN --mount=type=cache,target=${CCACHE_DIR} \
|
|||||||
if [ "$BUILD_TRITON" = "1" ]; then \
|
if [ "$BUILD_TRITON" = "1" ]; then \
|
||||||
mkdir -p libs \
|
mkdir -p libs \
|
||||||
&& cd libs \
|
&& cd libs \
|
||||||
|
&& python3 -m pip install ninja cmake wheel pybind11 \
|
||||||
&& git clone https://github.com/OpenAI/triton.git \
|
&& git clone https://github.com/OpenAI/triton.git \
|
||||||
&& cd triton \
|
&& cd triton \
|
||||||
&& git checkout "${TRITON_BRANCH}" \
|
&& git checkout "${TRITON_BRANCH}" \
|
||||||
@@ -129,7 +120,7 @@ COPY . .
|
|||||||
|
|
||||||
# Package upgrades for useful functionality or to avoid dependency issues
|
# Package upgrades for useful functionality or to avoid dependency issues
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
python3 -m pip install --upgrade numba scipy huggingface-hub[cli]
|
python3 -m pip install --upgrade numba scipy huggingface-hub[cli] pytest-shard
|
||||||
|
|
||||||
|
|
||||||
# Workaround for ray >= 2.10.0
|
# Workaround for ray >= 2.10.0
|
||||||
@@ -138,15 +129,9 @@ ENV RAY_EXPERIMENTAL_NOSET_ROCR_VISIBLE_DEVICES=1
|
|||||||
ENV TOKENIZERS_PARALLELISM=false
|
ENV TOKENIZERS_PARALLELISM=false
|
||||||
|
|
||||||
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
RUN --mount=type=cache,target=${CCACHE_DIR} \
|
||||||
|
--mount=type=bind,source=.git,target=.git \
|
||||||
--mount=type=cache,target=/root/.cache/pip \
|
--mount=type=cache,target=/root/.cache/pip \
|
||||||
python3 -m pip install -Ur requirements-rocm.txt \
|
python3 -m pip install -Ur requirements-rocm.txt \
|
||||||
&& case "$(ls /opt | grep -Po 'rocm-[0-9]\.[0-9]')" in \
|
|
||||||
*"rocm-6.1"*) \
|
|
||||||
# Bring in upgrades to HIP graph earlier than ROCm 6.2 for vLLM
|
|
||||||
wget -N https://github.com/ROCm/vllm/raw/fa78403/rocm_patch/libamdhip64.so.6 -P /opt/rocm/lib \
|
|
||||||
# Prevent interference if torch bundles its own HIP runtime
|
|
||||||
&& rm -f "$(python3 -c 'import torch; print(torch.__path__[0])')"/lib/libamdhip64.so* || true;; \
|
|
||||||
*) ;; esac \
|
|
||||||
&& python3 setup.py clean --all \
|
&& python3 setup.py clean --all \
|
||||||
&& python3 setup.py develop
|
&& python3 setup.py develop
|
||||||
|
|
||||||
|
|||||||
@@ -5,16 +5,25 @@ FROM $BASE_IMAGE
|
|||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
|
|
||||||
# Install some basic utilities
|
# Install some basic utilities
|
||||||
RUN apt-get update && apt-get install -y ffmpeg libsm6 libxext6 libgl1
|
RUN apt-get update && apt-get install -y \
|
||||||
|
git \
|
||||||
|
ffmpeg libsm6 libxext6 libgl1
|
||||||
|
|
||||||
# Install the TPU and Pallas dependencies.
|
# Install the TPU and Pallas dependencies.
|
||||||
RUN python3 -m pip install torch_xla[tpu] -f https://storage.googleapis.com/libtpu-releases/index.html
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
RUN python3 -m pip install torch_xla[pallas] -f https://storage.googleapis.com/jax-releases/jax_nightly_releases.html -f https://storage.googleapis.com/jax-releases/jaxlib_nightly_releases.html
|
python3 -m pip install torch_xla[tpu] -f https://storage.googleapis.com/libtpu-releases/index.html
|
||||||
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
python3 -m pip install torch_xla[pallas] -f https://storage.googleapis.com/jax-releases/jax_nightly_releases.html -f https://storage.googleapis.com/jax-releases/jaxlib_nightly_releases.html
|
||||||
|
|
||||||
# Build vLLM.
|
# Build vLLM.
|
||||||
COPY . /workspace/vllm
|
COPY . /workspace/vllm
|
||||||
ENV VLLM_TARGET_DEVICE="tpu"
|
ENV VLLM_TARGET_DEVICE="tpu"
|
||||||
RUN cd /workspace/vllm && python3 -m pip install -r requirements-tpu.txt
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
--mount=type=bind,source=.git,target=.git \
|
||||||
|
cd /workspace/vllm && \
|
||||||
|
python3 -m pip install \
|
||||||
|
cmake>=3.26 ninja packaging setuptools-scm>=8 wheel jinja2 \
|
||||||
|
-r requirements-tpu.txt
|
||||||
RUN cd /workspace/vllm && python3 setup.py develop
|
RUN cd /workspace/vllm && python3 setup.py develop
|
||||||
|
|
||||||
CMD ["/bin/bash"]
|
CMD ["/bin/bash"]
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
FROM intel/oneapi-basekit:2024.1.0-devel-ubuntu20.04
|
FROM intel/oneapi-basekit:2024.2.1-0-devel-ubuntu22.04
|
||||||
|
|
||||||
RUN wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | tee /usr/share/keyrings/intel-oneapi-archive-keyring.gpg > /dev/null && \
|
RUN wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | tee /usr/share/keyrings/intel-oneapi-archive-keyring.gpg > /dev/null && \
|
||||||
echo "deb [signed-by=/usr/share/keyrings/intel-oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main " | tee /etc/apt/sources.list.d/oneAPI.list && \
|
echo "deb [signed-by=/usr/share/keyrings/intel-oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main " | tee /etc/apt/sources.list.d/oneAPI.list && \
|
||||||
chmod 644 /usr/share/keyrings/intel-oneapi-archive-keyring.gpg && \
|
chmod 644 /usr/share/keyrings/intel-oneapi-archive-keyring.gpg && \
|
||||||
rm /etc/apt/sources.list.d/intel-graphics.list && \
|
|
||||||
wget -O- https://repositories.intel.com/graphics/intel-graphics.key | gpg --dearmor | tee /usr/share/keyrings/intel-graphics.gpg > /dev/null && \
|
wget -O- https://repositories.intel.com/graphics/intel-graphics.key | gpg --dearmor | tee /usr/share/keyrings/intel-graphics.gpg > /dev/null && \
|
||||||
echo "deb [arch=amd64,i386 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/graphics/ubuntu jammy arc" | tee /etc/apt/sources.list.d/intel.gpu.jammy.list && \
|
echo "deb [arch=amd64,i386 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/graphics/ubuntu jammy arc" | tee /etc/apt/sources.list.d/intel.gpu.jammy.list && \
|
||||||
chmod 644 /usr/share/keyrings/intel-graphics.gpg
|
chmod 644 /usr/share/keyrings/intel-graphics.gpg
|
||||||
|
|
||||||
RUN apt-get update -y \
|
RUN apt-get update -y && \
|
||||||
&& apt-get install -y curl libicu70 lsb-release git wget vim numactl python3 python3-pip ffmpeg libsm6 libxext6 libgl1
|
apt-get install -y curl libicu70 lsb-release git wget vim numactl python3 python3-pip ffmpeg libsm6 libxext6 libgl1
|
||||||
|
|
||||||
COPY ./ /workspace/vllm
|
COPY ./ /workspace/vllm
|
||||||
|
|
||||||
WORKDIR /workspace/vllm
|
WORKDIR /workspace/vllm
|
||||||
|
|
||||||
RUN pip install -v -r requirements-xpu.txt
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
pip install -v --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/xpu/us/ \
|
||||||
|
cmake>=3.26 ninja packaging setuptools-scm>=8 wheel jinja2 \
|
||||||
|
-r requirements-xpu.txt
|
||||||
|
|
||||||
RUN VLLM_TARGET_DEVICE=xpu python3 setup.py install
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
|
--mount=type=bind,source=.git,target=.git \
|
||||||
|
VLLM_TARGET_DEVICE=xpu python3 setup.py install
|
||||||
|
|
||||||
CMD ["/bin/bash"]
|
CMD ["/bin/bash"]
|
||||||
|
|||||||
12
SECURITY.md
Normal file
12
SECURITY.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you believe you have found a security vulnerability in vLLM, we encourage you to let us know right away.
|
||||||
|
We will investigate all legitimate reports and do our best to quickly fix the problem.
|
||||||
|
|
||||||
|
Please report security issues using https://github.com/vllm-project/vllm/security/advisories/new
|
||||||
|
|
||||||
|
---
|
||||||
|
Please see PyTorch Security for more information how to securely interact with models: https://github.com/pytorch/pytorch/blob/main/SECURITY.md
|
||||||
|
This document mostly references the recommendation from PyTorch, thank you!
|
||||||
@@ -25,6 +25,7 @@ class RequestFuncInput:
|
|||||||
best_of: int = 1
|
best_of: int = 1
|
||||||
use_beam_search: bool = False
|
use_beam_search: bool = False
|
||||||
logprobs: Optional[int] = None
|
logprobs: Optional[int] = None
|
||||||
|
multi_modal_content: Optional[dict] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -312,12 +313,15 @@ async def async_request_openai_chat_completions(
|
|||||||
|
|
||||||
async with aiohttp.ClientSession(timeout=AIOHTTP_TIMEOUT) as session:
|
async with aiohttp.ClientSession(timeout=AIOHTTP_TIMEOUT) as session:
|
||||||
assert not request_func_input.use_beam_search
|
assert not request_func_input.use_beam_search
|
||||||
|
content = [{"type": "text", "text": request_func_input.prompt}]
|
||||||
|
if request_func_input.multi_modal_content:
|
||||||
|
content.append(request_func_input.multi_modal_content)
|
||||||
payload = {
|
payload = {
|
||||||
"model": request_func_input.model,
|
"model": request_func_input.model,
|
||||||
"messages": [
|
"messages": [
|
||||||
{
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": request_func_input.prompt,
|
"content": content
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"temperature": 0.0,
|
"temperature": 0.0,
|
||||||
|
|||||||
295
benchmarks/benchmark_prioritization.py
Normal file
295
benchmarks/benchmark_prioritization.py
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
"""Benchmark offline prioritization."""
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
|
from transformers import AutoTokenizer, PreTrainedTokenizerBase
|
||||||
|
|
||||||
|
from vllm.model_executor.layers.quantization import QUANTIZATION_METHODS
|
||||||
|
|
||||||
|
|
||||||
|
def sample_requests(
|
||||||
|
dataset_path: str,
|
||||||
|
num_requests: int,
|
||||||
|
tokenizer: PreTrainedTokenizerBase,
|
||||||
|
fixed_output_len: Optional[int],
|
||||||
|
) -> List[Tuple[str, int, int]]:
|
||||||
|
if fixed_output_len is not None and fixed_output_len < 4:
|
||||||
|
raise ValueError("output_len too small")
|
||||||
|
|
||||||
|
# Load the dataset.
|
||||||
|
with open(dataset_path) as f:
|
||||||
|
dataset = json.load(f)
|
||||||
|
# Filter out the conversations with less than 2 turns.
|
||||||
|
dataset = [data for data in dataset if len(data["conversations"]) >= 2]
|
||||||
|
# Only keep the first two turns of each conversation.
|
||||||
|
dataset = [(data["conversations"][0]["value"],
|
||||||
|
data["conversations"][1]["value"]) for data in dataset]
|
||||||
|
|
||||||
|
# Shuffle the dataset.
|
||||||
|
random.shuffle(dataset)
|
||||||
|
|
||||||
|
# Filter out sequences that are too long or too short
|
||||||
|
filtered_dataset: List[Tuple[str, int, int]] = []
|
||||||
|
for i in range(len(dataset)):
|
||||||
|
if len(filtered_dataset) == num_requests:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Tokenize the prompts and completions.
|
||||||
|
prompt = dataset[i][0]
|
||||||
|
prompt_token_ids = tokenizer(prompt).input_ids
|
||||||
|
completion = dataset[i][1]
|
||||||
|
completion_token_ids = tokenizer(completion).input_ids
|
||||||
|
prompt_len = len(prompt_token_ids)
|
||||||
|
output_len = len(completion_token_ids
|
||||||
|
) if fixed_output_len is None else fixed_output_len
|
||||||
|
if prompt_len < 4 or output_len < 4:
|
||||||
|
# Prune too short sequences.
|
||||||
|
continue
|
||||||
|
if prompt_len > 1024 or prompt_len + output_len > 2048:
|
||||||
|
# Prune too long sequences.
|
||||||
|
continue
|
||||||
|
|
||||||
|
#Select a equi-probable random priority
|
||||||
|
priority = 0 if random.random() < 0.5 else 1
|
||||||
|
|
||||||
|
filtered_dataset.append((prompt, prompt_len, output_len, priority))
|
||||||
|
|
||||||
|
return filtered_dataset
|
||||||
|
|
||||||
|
|
||||||
|
def run_vllm(
|
||||||
|
requests: List[Tuple[str, int, int]],
|
||||||
|
model: str,
|
||||||
|
tokenizer: str,
|
||||||
|
quantization: Optional[str],
|
||||||
|
tensor_parallel_size: int,
|
||||||
|
seed: int,
|
||||||
|
n: int,
|
||||||
|
use_beam_search: bool,
|
||||||
|
trust_remote_code: bool,
|
||||||
|
dtype: str,
|
||||||
|
max_model_len: Optional[int],
|
||||||
|
enforce_eager: bool,
|
||||||
|
kv_cache_dtype: str,
|
||||||
|
quantization_param_path: Optional[str],
|
||||||
|
device: str,
|
||||||
|
enable_prefix_caching: bool,
|
||||||
|
enable_chunked_prefill: bool,
|
||||||
|
max_num_batched_tokens: int,
|
||||||
|
gpu_memory_utilization: float = 0.9,
|
||||||
|
download_dir: Optional[str] = None,
|
||||||
|
) -> float:
|
||||||
|
from vllm import LLM, SamplingParams
|
||||||
|
llm = LLM(
|
||||||
|
model=model,
|
||||||
|
tokenizer=tokenizer,
|
||||||
|
quantization=quantization,
|
||||||
|
tensor_parallel_size=tensor_parallel_size,
|
||||||
|
seed=seed,
|
||||||
|
trust_remote_code=trust_remote_code,
|
||||||
|
dtype=dtype,
|
||||||
|
max_model_len=max_model_len,
|
||||||
|
gpu_memory_utilization=gpu_memory_utilization,
|
||||||
|
enforce_eager=enforce_eager,
|
||||||
|
kv_cache_dtype=kv_cache_dtype,
|
||||||
|
quantization_param_path=quantization_param_path,
|
||||||
|
device=device,
|
||||||
|
enable_prefix_caching=enable_prefix_caching,
|
||||||
|
download_dir=download_dir,
|
||||||
|
enable_chunked_prefill=enable_chunked_prefill,
|
||||||
|
max_num_batched_tokens=max_num_batched_tokens,
|
||||||
|
disable_log_stats=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the requests to the engine.
|
||||||
|
prompts = []
|
||||||
|
sampling_params = []
|
||||||
|
priority = []
|
||||||
|
for prompt, _, output_len, _priority in requests:
|
||||||
|
prompts.append(prompt)
|
||||||
|
priority.append(_priority)
|
||||||
|
sampling_params.append(
|
||||||
|
SamplingParams(
|
||||||
|
n=n,
|
||||||
|
temperature=0.0 if use_beam_search else 1.0,
|
||||||
|
top_p=1.0,
|
||||||
|
use_beam_search=use_beam_search,
|
||||||
|
ignore_eos=True,
|
||||||
|
max_tokens=output_len,
|
||||||
|
))
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
llm.generate(prompts, sampling_params, priority=priority, use_tqdm=True)
|
||||||
|
end = time.perf_counter()
|
||||||
|
return end - start
|
||||||
|
|
||||||
|
|
||||||
|
def main(args: argparse.Namespace):
|
||||||
|
print(args)
|
||||||
|
random.seed(args.seed)
|
||||||
|
|
||||||
|
# Sample the requests.
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained(
|
||||||
|
args.tokenizer, trust_remote_code=args.trust_remote_code)
|
||||||
|
if args.dataset is None:
|
||||||
|
# Synthesize a prompt with the given input length.
|
||||||
|
prompt = "hi" * (args.input_len - 1)
|
||||||
|
requests = [(prompt, args.input_len, args.output_len)
|
||||||
|
for _ in range(args.num_prompts)]
|
||||||
|
else:
|
||||||
|
requests = sample_requests(args.dataset, args.num_prompts, tokenizer,
|
||||||
|
args.output_len)
|
||||||
|
|
||||||
|
if args.backend == "vllm":
|
||||||
|
elapsed_time = run_vllm(
|
||||||
|
requests, args.model, args.tokenizer, args.quantization,
|
||||||
|
args.tensor_parallel_size, args.seed, args.n, args.use_beam_search,
|
||||||
|
args.trust_remote_code, args.dtype, args.max_model_len,
|
||||||
|
args.enforce_eager, args.kv_cache_dtype,
|
||||||
|
args.quantization_param_path, args.device,
|
||||||
|
args.enable_prefix_caching, args.enable_chunked_prefill,
|
||||||
|
args.max_num_batched_tokens, args.gpu_memory_utilization,
|
||||||
|
args.download_dir)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unknown backend: {args.backend}")
|
||||||
|
total_num_tokens = sum(prompt_len + output_len
|
||||||
|
for _, prompt_len, output_len, priority in requests)
|
||||||
|
print(f"Throughput: {len(requests) / elapsed_time:.2f} requests/s, "
|
||||||
|
f"{total_num_tokens / elapsed_time:.2f} tokens/s")
|
||||||
|
|
||||||
|
# Output JSON results if specified
|
||||||
|
if args.output_json:
|
||||||
|
results = {
|
||||||
|
"elapsed_time": elapsed_time,
|
||||||
|
"num_requests": len(requests),
|
||||||
|
"total_num_tokens": total_num_tokens,
|
||||||
|
"requests_per_second": len(requests) / elapsed_time,
|
||||||
|
"tokens_per_second": total_num_tokens / elapsed_time,
|
||||||
|
}
|
||||||
|
with open(args.output_json, "w") as f:
|
||||||
|
json.dump(results, f, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Benchmark the throughput.")
|
||||||
|
parser.add_argument("--backend",
|
||||||
|
type=str,
|
||||||
|
choices=["vllm", "hf", "mii"],
|
||||||
|
default="vllm")
|
||||||
|
parser.add_argument("--dataset",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="Path to the dataset.")
|
||||||
|
parser.add_argument("--input-len",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Input prompt length for each request")
|
||||||
|
parser.add_argument("--output-len",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Output length for each request. Overrides the "
|
||||||
|
"output length from the dataset.")
|
||||||
|
parser.add_argument("--model", type=str, default="facebook/opt-125m")
|
||||||
|
parser.add_argument("--tokenizer", type=str, default=None)
|
||||||
|
parser.add_argument('--quantization',
|
||||||
|
'-q',
|
||||||
|
choices=[*QUANTIZATION_METHODS, None],
|
||||||
|
default=None)
|
||||||
|
parser.add_argument("--tensor-parallel-size", "-tp", type=int, default=1)
|
||||||
|
parser.add_argument("--n",
|
||||||
|
type=int,
|
||||||
|
default=1,
|
||||||
|
help="Number of generated sequences per prompt.")
|
||||||
|
parser.add_argument("--use-beam-search", action="store_true")
|
||||||
|
parser.add_argument("--num-prompts",
|
||||||
|
type=int,
|
||||||
|
default=200,
|
||||||
|
help="Number of prompts to process.")
|
||||||
|
parser.add_argument("--seed", type=int, default=0)
|
||||||
|
parser.add_argument('--trust-remote-code',
|
||||||
|
action='store_true',
|
||||||
|
help='trust remote code from huggingface')
|
||||||
|
parser.add_argument(
|
||||||
|
'--max-model-len',
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help='Maximum length of a sequence (including prompt and output). '
|
||||||
|
'If None, will be derived from the model.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--dtype',
|
||||||
|
type=str,
|
||||||
|
default='auto',
|
||||||
|
choices=['auto', 'half', 'float16', 'bfloat16', 'float', 'float32'],
|
||||||
|
help='data type for model weights and activations. '
|
||||||
|
'The "auto" option will use FP16 precision '
|
||||||
|
'for FP32 and FP16 models, and BF16 precision '
|
||||||
|
'for BF16 models.')
|
||||||
|
parser.add_argument('--gpu-memory-utilization',
|
||||||
|
type=float,
|
||||||
|
default=0.9,
|
||||||
|
help='the fraction of GPU memory to be used for '
|
||||||
|
'the model executor, which can range from 0 to 1.'
|
||||||
|
'If unspecified, will use the default value of 0.9.')
|
||||||
|
parser.add_argument("--enforce-eager",
|
||||||
|
action="store_true",
|
||||||
|
help="enforce eager execution")
|
||||||
|
parser.add_argument(
|
||||||
|
'--kv-cache-dtype',
|
||||||
|
type=str,
|
||||||
|
choices=['auto', 'fp8', 'fp8_e5m2', 'fp8_e4m3'],
|
||||||
|
default="auto",
|
||||||
|
help='Data type for kv cache storage. If "auto", will use model '
|
||||||
|
'data type. CUDA 11.8+ supports fp8 (=fp8_e4m3) and fp8_e5m2. '
|
||||||
|
'ROCm (AMD GPU) supports fp8 (=fp8_e4m3)')
|
||||||
|
parser.add_argument(
|
||||||
|
'--quantization-param-path',
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help='Path to the JSON file containing the KV cache scaling factors. '
|
||||||
|
'This should generally be supplied, when KV cache dtype is FP8. '
|
||||||
|
'Otherwise, KV cache scaling factors default to 1.0, which may cause '
|
||||||
|
'accuracy issues. FP8_E5M2 (without scaling) is only supported on '
|
||||||
|
'cuda version greater than 11.8. On ROCm (AMD GPU), FP8_E4M3 is '
|
||||||
|
'instead supported for common inference criteria.')
|
||||||
|
parser.add_argument(
|
||||||
|
"--device",
|
||||||
|
type=str,
|
||||||
|
default="cuda",
|
||||||
|
choices=["cuda", "cpu"],
|
||||||
|
help='device type for vLLM execution, supporting CUDA and CPU.')
|
||||||
|
parser.add_argument(
|
||||||
|
"--enable-prefix-caching",
|
||||||
|
action='store_true',
|
||||||
|
help="enable automatic prefix caching for vLLM backend.")
|
||||||
|
parser.add_argument("--enable-chunked-prefill",
|
||||||
|
action='store_true',
|
||||||
|
help="enable chunked prefill for vLLM backend.")
|
||||||
|
parser.add_argument('--max-num-batched-tokens',
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help='maximum number of batched tokens per '
|
||||||
|
'iteration')
|
||||||
|
parser.add_argument('--download-dir',
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help='directory to download and load the weights, '
|
||||||
|
'default to the default cache dir of huggingface')
|
||||||
|
parser.add_argument(
|
||||||
|
'--output-json',
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help='Path to save the throughput results in JSON format.')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
if args.tokenizer is None:
|
||||||
|
args.tokenizer = args.model
|
||||||
|
if args.dataset is None:
|
||||||
|
assert args.input_len is not None
|
||||||
|
assert args.output_len is not None
|
||||||
|
else:
|
||||||
|
assert args.input_len is None
|
||||||
|
|
||||||
|
main(args)
|
||||||
@@ -24,6 +24,8 @@ On the client side, run:
|
|||||||
"""
|
"""
|
||||||
import argparse
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import base64
|
||||||
|
import io
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
@@ -31,11 +33,13 @@ import time
|
|||||||
import warnings
|
import warnings
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, AsyncGenerator, Dict, List, Optional, Tuple
|
from typing import Any, AsyncGenerator, Collection, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from backend_request_func import (ASYNC_REQUEST_FUNCS, RequestFuncInput,
|
from backend_request_func import (ASYNC_REQUEST_FUNCS, RequestFuncInput,
|
||||||
RequestFuncOutput)
|
RequestFuncOutput)
|
||||||
|
from datasets import load_dataset
|
||||||
|
from PIL.Image import Image
|
||||||
from tqdm.asyncio import tqdm
|
from tqdm.asyncio import tqdm
|
||||||
from transformers import PreTrainedTokenizerBase
|
from transformers import PreTrainedTokenizerBase
|
||||||
|
|
||||||
@@ -84,7 +88,7 @@ def sample_sharegpt_requests(
|
|||||||
num_requests: int,
|
num_requests: int,
|
||||||
tokenizer: PreTrainedTokenizerBase,
|
tokenizer: PreTrainedTokenizerBase,
|
||||||
fixed_output_len: Optional[int] = None,
|
fixed_output_len: Optional[int] = None,
|
||||||
) -> List[Tuple[str, int, int]]:
|
) -> List[Tuple[str, int, int, None]]:
|
||||||
if fixed_output_len is not None and fixed_output_len < 4:
|
if fixed_output_len is not None and fixed_output_len < 4:
|
||||||
raise ValueError("output_len too small")
|
raise ValueError("output_len too small")
|
||||||
# Load the dataset.
|
# Load the dataset.
|
||||||
@@ -119,7 +123,7 @@ def sample_sharegpt_requests(
|
|||||||
if prompt_len > 1024 or prompt_len + output_len > 2048:
|
if prompt_len > 1024 or prompt_len + output_len > 2048:
|
||||||
# Prune too long sequences.
|
# Prune too long sequences.
|
||||||
continue
|
continue
|
||||||
filtered_dataset.append((prompt, prompt_len, output_len))
|
filtered_dataset.append((prompt, prompt_len, output_len, None))
|
||||||
|
|
||||||
return filtered_dataset
|
return filtered_dataset
|
||||||
|
|
||||||
@@ -131,7 +135,7 @@ def sample_sonnet_requests(
|
|||||||
output_len: int,
|
output_len: int,
|
||||||
prefix_len: int,
|
prefix_len: int,
|
||||||
tokenizer: PreTrainedTokenizerBase,
|
tokenizer: PreTrainedTokenizerBase,
|
||||||
) -> List[Tuple[str, str, int, int]]:
|
) -> List[Tuple[str, str, int, int, None]]:
|
||||||
assert (
|
assert (
|
||||||
input_len > prefix_len
|
input_len > prefix_len
|
||||||
), "'args.sonnet-input-len' must be greater than 'args.prefix-input-len'."
|
), "'args.sonnet-input-len' must be greater than 'args.prefix-input-len'."
|
||||||
@@ -189,7 +193,65 @@ def sample_sonnet_requests(
|
|||||||
message, add_generation_prompt=True, tokenize=False)
|
message, add_generation_prompt=True, tokenize=False)
|
||||||
prompt_len = len(tokenizer(prompt_formatted).input_ids)
|
prompt_len = len(tokenizer(prompt_formatted).input_ids)
|
||||||
sampled_requests.append(
|
sampled_requests.append(
|
||||||
(prompt, prompt_formatted, prompt_len, output_len))
|
(prompt, prompt_formatted, prompt_len, output_len, None))
|
||||||
|
|
||||||
|
return sampled_requests
|
||||||
|
|
||||||
|
|
||||||
|
def sample_hf_requests(
|
||||||
|
dataset_path: str,
|
||||||
|
dataset_subset: str,
|
||||||
|
dataset_split: str,
|
||||||
|
num_requests: int,
|
||||||
|
tokenizer: PreTrainedTokenizerBase,
|
||||||
|
fixed_output_len: Optional[int] = None,
|
||||||
|
) -> List[Tuple[str, str, int, Optional[Dict[str, Collection[str]]]]]:
|
||||||
|
dataset = load_dataset(dataset_path,
|
||||||
|
name=dataset_subset,
|
||||||
|
split=dataset_split,
|
||||||
|
streaming=True)
|
||||||
|
assert "conversations" in dataset.features, (
|
||||||
|
"HF Dataset must have 'conversations' column.")
|
||||||
|
filtered_dataset = dataset.shuffle().filter(
|
||||||
|
lambda x: len(x["conversations"]) >= 2)
|
||||||
|
sampled_requests: List[Tuple[str, int, int, Dict[str,
|
||||||
|
Collection[str]]]] = []
|
||||||
|
for data in filtered_dataset:
|
||||||
|
if len(sampled_requests) == num_requests:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Tokenize the prompts and completions.
|
||||||
|
prompt = data["conversations"][0]["value"]
|
||||||
|
prompt_token_ids = tokenizer(prompt).input_ids
|
||||||
|
completion = data["conversations"][1]["value"]
|
||||||
|
completion_token_ids = tokenizer(completion).input_ids
|
||||||
|
prompt_len = len(prompt_token_ids)
|
||||||
|
output_len = len(completion_token_ids
|
||||||
|
) if fixed_output_len is None else fixed_output_len
|
||||||
|
if prompt_len < 4 or output_len < 4:
|
||||||
|
# Prune too short sequences.
|
||||||
|
continue
|
||||||
|
if prompt_len > 1024 or prompt_len + output_len > 2048:
|
||||||
|
# Prune too long sequences.
|
||||||
|
continue
|
||||||
|
|
||||||
|
if "image" in data and isinstance(data["image"], Image):
|
||||||
|
image: Image = data["image"]
|
||||||
|
image = image.convert("RGB")
|
||||||
|
image_data = io.BytesIO()
|
||||||
|
image.save(image_data, format='JPEG')
|
||||||
|
image_base64 = base64.b64encode(
|
||||||
|
image_data.getvalue()).decode("utf-8")
|
||||||
|
mm_content = {
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {
|
||||||
|
"url": f"data:image/jpeg;base64,{image_base64}"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
mm_content = None
|
||||||
|
|
||||||
|
sampled_requests.append((prompt, prompt_len, output_len, mm_content))
|
||||||
|
|
||||||
return sampled_requests
|
return sampled_requests
|
||||||
|
|
||||||
@@ -223,8 +285,8 @@ def sample_random_requests(
|
|||||||
[(offsets[i] + i + j) % tokenizer.vocab_size
|
[(offsets[i] + i + j) % tokenizer.vocab_size
|
||||||
for j in range(input_lens[i])])
|
for j in range(input_lens[i])])
|
||||||
|
|
||||||
input_requests.append(
|
input_requests.append((prompt, int(prefix_len + input_lens[i]),
|
||||||
(prompt, int(prefix_len + input_lens[i]), int(output_lens[i])))
|
int(output_lens[i]), None))
|
||||||
|
|
||||||
return input_requests
|
return input_requests
|
||||||
|
|
||||||
@@ -343,7 +405,12 @@ async def benchmark(
|
|||||||
raise ValueError(f"Unknown backend: {backend}")
|
raise ValueError(f"Unknown backend: {backend}")
|
||||||
|
|
||||||
print("Starting initial single prompt test run...")
|
print("Starting initial single prompt test run...")
|
||||||
test_prompt, test_prompt_len, test_output_len = input_requests[0]
|
test_prompt, test_prompt_len, test_output_len, test_mm_content = (
|
||||||
|
input_requests[0])
|
||||||
|
if backend != "openai-chat" and test_mm_content is not None:
|
||||||
|
# multi-modal benchmark is only available on OpenAI Chat backend.
|
||||||
|
raise ValueError(
|
||||||
|
"Multi-modal content is only supported on 'openai-chat' backend.")
|
||||||
test_input = RequestFuncInput(
|
test_input = RequestFuncInput(
|
||||||
model=model_id,
|
model=model_id,
|
||||||
prompt=test_prompt,
|
prompt=test_prompt,
|
||||||
@@ -353,6 +420,7 @@ async def benchmark(
|
|||||||
logprobs=logprobs,
|
logprobs=logprobs,
|
||||||
best_of=best_of,
|
best_of=best_of,
|
||||||
use_beam_search=use_beam_search,
|
use_beam_search=use_beam_search,
|
||||||
|
multi_modal_content=test_mm_content,
|
||||||
)
|
)
|
||||||
test_output = await request_func(request_func_input=test_input)
|
test_output = await request_func(request_func_input=test_input)
|
||||||
if not test_output.success:
|
if not test_output.success:
|
||||||
@@ -373,6 +441,7 @@ async def benchmark(
|
|||||||
logprobs=logprobs,
|
logprobs=logprobs,
|
||||||
best_of=best_of,
|
best_of=best_of,
|
||||||
use_beam_search=use_beam_search,
|
use_beam_search=use_beam_search,
|
||||||
|
multi_modal_content=test_mm_content,
|
||||||
)
|
)
|
||||||
profile_output = await request_func(request_func_input=profile_input)
|
profile_output = await request_func(request_func_input=profile_input)
|
||||||
if profile_output.success:
|
if profile_output.success:
|
||||||
@@ -385,7 +454,7 @@ async def benchmark(
|
|||||||
benchmark_start_time = time.perf_counter()
|
benchmark_start_time = time.perf_counter()
|
||||||
tasks: List[asyncio.Task] = []
|
tasks: List[asyncio.Task] = []
|
||||||
async for request in get_request(input_requests, request_rate):
|
async for request in get_request(input_requests, request_rate):
|
||||||
prompt, prompt_len, output_len = request
|
prompt, prompt_len, output_len, mm_content = request
|
||||||
request_func_input = RequestFuncInput(
|
request_func_input = RequestFuncInput(
|
||||||
model=model_id,
|
model=model_id,
|
||||||
prompt=prompt,
|
prompt=prompt,
|
||||||
@@ -395,6 +464,7 @@ async def benchmark(
|
|||||||
logprobs=logprobs,
|
logprobs=logprobs,
|
||||||
best_of=best_of,
|
best_of=best_of,
|
||||||
use_beam_search=use_beam_search,
|
use_beam_search=use_beam_search,
|
||||||
|
multi_modal_content=mm_content,
|
||||||
)
|
)
|
||||||
tasks.append(
|
tasks.append(
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
@@ -556,9 +626,9 @@ def main(args: argparse.Namespace):
|
|||||||
prefix_len=args.sonnet_prefix_len,
|
prefix_len=args.sonnet_prefix_len,
|
||||||
tokenizer=tokenizer,
|
tokenizer=tokenizer,
|
||||||
)
|
)
|
||||||
input_requests = [(prompt, prompt_len, output_len)
|
input_requests = [(prompt, prompt_len, output_len, None)
|
||||||
for prompt, prompt_formatted, prompt_len,
|
for prompt, prompt_formatted, prompt_len,
|
||||||
output_len in input_requests]
|
output_len, _ in input_requests]
|
||||||
else:
|
else:
|
||||||
assert (
|
assert (
|
||||||
tokenizer.chat_template or tokenizer.default_chat_template
|
tokenizer.chat_template or tokenizer.default_chat_template
|
||||||
@@ -571,9 +641,19 @@ def main(args: argparse.Namespace):
|
|||||||
prefix_len=args.sonnet_prefix_len,
|
prefix_len=args.sonnet_prefix_len,
|
||||||
tokenizer=tokenizer,
|
tokenizer=tokenizer,
|
||||||
)
|
)
|
||||||
input_requests = [(prompt_formatted, prompt_len, output_len)
|
input_requests = [(prompt_formatted, prompt_len, output_len, None)
|
||||||
for prompt, prompt_formatted, prompt_len,
|
for prompt, prompt_formatted, prompt_len,
|
||||||
output_len in input_requests]
|
output_len, _ in input_requests]
|
||||||
|
|
||||||
|
elif args.dataset_name == "hf":
|
||||||
|
input_requests = sample_hf_requests(
|
||||||
|
dataset_path=args.dataset_path,
|
||||||
|
dataset_subset=args.hf_subset,
|
||||||
|
dataset_split=args.hf_split,
|
||||||
|
num_requests=args.num_prompts,
|
||||||
|
tokenizer=tokenizer,
|
||||||
|
fixed_output_len=args.hf_output_len,
|
||||||
|
)
|
||||||
|
|
||||||
elif args.dataset_name == "random":
|
elif args.dataset_name == "random":
|
||||||
input_requests = sample_random_requests(
|
input_requests = sample_random_requests(
|
||||||
@@ -685,13 +765,14 @@ if __name__ == "__main__":
|
|||||||
"--dataset-name",
|
"--dataset-name",
|
||||||
type=str,
|
type=str,
|
||||||
default="sharegpt",
|
default="sharegpt",
|
||||||
choices=["sharegpt", "sonnet", "random"],
|
choices=["sharegpt", "sonnet", "random", "hf"],
|
||||||
help="Name of the dataset to benchmark on.",
|
help="Name of the dataset to benchmark on.",
|
||||||
)
|
)
|
||||||
parser.add_argument("--dataset-path",
|
parser.add_argument("--dataset-path",
|
||||||
type=str,
|
type=str,
|
||||||
default=None,
|
default=None,
|
||||||
help="Path to the dataset.")
|
help="Path to the sharegpt/sonnet dataset. "
|
||||||
|
"Or the huggingface dataset ID if using HF dataset.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--model",
|
"--model",
|
||||||
type=str,
|
type=str,
|
||||||
@@ -718,26 +799,6 @@ if __name__ == "__main__":
|
|||||||
default=1000,
|
default=1000,
|
||||||
help="Number of prompts to process.",
|
help="Number of prompts to process.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"--sharegpt-output-len",
|
|
||||||
type=int,
|
|
||||||
default=None,
|
|
||||||
help="Output length for each request. Overrides the output length "
|
|
||||||
"from the ShareGPT dataset.")
|
|
||||||
parser.add_argument(
|
|
||||||
"--sonnet-input-len",
|
|
||||||
type=int,
|
|
||||||
default=550,
|
|
||||||
help=
|
|
||||||
"Number of input tokens per request, used only for sonnet dataset.",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--sonnet-output-len",
|
|
||||||
type=int,
|
|
||||||
default=150,
|
|
||||||
help=
|
|
||||||
"Number of output tokens per request, used only for sonnet dataset.",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--logprobs",
|
"--logprobs",
|
||||||
type=int,
|
type=int,
|
||||||
@@ -748,42 +809,6 @@ if __name__ == "__main__":
|
|||||||
"logprob is returned for each token; or (2) if beam search "
|
"logprob is returned for each token; or (2) if beam search "
|
||||||
"is enabled 1 logprob per token is computed"),
|
"is enabled 1 logprob per token is computed"),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"--sonnet-prefix-len",
|
|
||||||
type=int,
|
|
||||||
default=200,
|
|
||||||
help=
|
|
||||||
"Number of prefix tokens per request, used only for sonnet dataset.",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--random-input-len",
|
|
||||||
type=int,
|
|
||||||
default=1024,
|
|
||||||
help=
|
|
||||||
"Number of input tokens per request, used only for random sampling.",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--random-output-len",
|
|
||||||
type=int,
|
|
||||||
default=128,
|
|
||||||
help=
|
|
||||||
"Number of output tokens per request, used only for random sampling.",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--random-range-ratio",
|
|
||||||
type=float,
|
|
||||||
default=1.0,
|
|
||||||
help="Range of sampled ratio of input/output length, "
|
|
||||||
"used only for random sampling.",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--random-prefix-len",
|
|
||||||
type=int,
|
|
||||||
default=0,
|
|
||||||
help="Number of fixed prefix tokens before random "
|
|
||||||
" context. The length range of context in a random "
|
|
||||||
" request is [random-prefix-len, "
|
|
||||||
" random-prefix-len + random-prefix-len * random-range-ratio).")
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--request-rate",
|
"--request-rate",
|
||||||
type=float,
|
type=float,
|
||||||
@@ -857,5 +882,85 @@ if __name__ == "__main__":
|
|||||||
"Use \"--percentile-metrics\" to select metrics.",
|
"Use \"--percentile-metrics\" to select metrics.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# group for dataset specific arguments
|
||||||
|
sonnet_group = parser.add_argument_group("sonnet dataset options")
|
||||||
|
sonnet_group.add_argument(
|
||||||
|
"--sonnet-input-len",
|
||||||
|
type=int,
|
||||||
|
default=550,
|
||||||
|
help=
|
||||||
|
"Number of input tokens per request, used only for sonnet dataset.",
|
||||||
|
)
|
||||||
|
sonnet_group.add_argument(
|
||||||
|
"--sonnet-output-len",
|
||||||
|
type=int,
|
||||||
|
default=150,
|
||||||
|
help=
|
||||||
|
"Number of output tokens per request, used only for sonnet dataset.",
|
||||||
|
)
|
||||||
|
sonnet_group.add_argument(
|
||||||
|
"--sonnet-prefix-len",
|
||||||
|
type=int,
|
||||||
|
default=200,
|
||||||
|
help=
|
||||||
|
"Number of prefix tokens per request, used only for sonnet dataset.",
|
||||||
|
)
|
||||||
|
|
||||||
|
sharegpt_group = parser.add_argument_group("sharegpt dataset options")
|
||||||
|
sharegpt_group.add_argument(
|
||||||
|
"--sharegpt-output-len",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Output length for each request. Overrides the output length "
|
||||||
|
"from the ShareGPT dataset.")
|
||||||
|
|
||||||
|
random_group = parser.add_argument_group("random dataset options")
|
||||||
|
random_group.add_argument(
|
||||||
|
"--random-input-len",
|
||||||
|
type=int,
|
||||||
|
default=1024,
|
||||||
|
help=
|
||||||
|
"Number of input tokens per request, used only for random sampling.",
|
||||||
|
)
|
||||||
|
random_group.add_argument(
|
||||||
|
"--random-output-len",
|
||||||
|
type=int,
|
||||||
|
default=128,
|
||||||
|
help=
|
||||||
|
"Number of output tokens per request, used only for random sampling.",
|
||||||
|
)
|
||||||
|
random_group.add_argument(
|
||||||
|
"--random-range-ratio",
|
||||||
|
type=float,
|
||||||
|
default=1.0,
|
||||||
|
help="Range of sampled ratio of input/output length, "
|
||||||
|
"used only for random sampling.",
|
||||||
|
)
|
||||||
|
random_group.add_argument(
|
||||||
|
"--random-prefix-len",
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help="Number of fixed prefix tokens before random "
|
||||||
|
" context. The length range of context in a random "
|
||||||
|
" request is [random-prefix-len, "
|
||||||
|
" random-prefix-len + random-prefix-len * random-range-ratio).")
|
||||||
|
|
||||||
|
hf_group = parser.add_argument_group("hf dataset options")
|
||||||
|
hf_group.add_argument("--hf-subset",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="Subset of the HF dataset.")
|
||||||
|
hf_group.add_argument("--hf-split",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="Split of the HF dataset.")
|
||||||
|
hf_group.add_argument(
|
||||||
|
"--hf-output-len",
|
||||||
|
type=int,
|
||||||
|
default=None,
|
||||||
|
help="Output length for each request. Overrides the output lengths "
|
||||||
|
"from the sampled HF dataset.",
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
main(args)
|
main(args)
|
||||||
@@ -90,6 +90,7 @@ def run_vllm(
|
|||||||
download_dir: Optional[str] = None,
|
download_dir: Optional[str] = None,
|
||||||
load_format: str = EngineArgs.load_format,
|
load_format: str = EngineArgs.load_format,
|
||||||
disable_async_output_proc: bool = False,
|
disable_async_output_proc: bool = False,
|
||||||
|
use_new_beam_search_impl: bool = False,
|
||||||
) -> float:
|
) -> float:
|
||||||
from vllm import LLM, SamplingParams
|
from vllm import LLM, SamplingParams
|
||||||
llm = LLM(
|
llm = LLM(
|
||||||
@@ -132,9 +133,23 @@ def run_vllm(
|
|||||||
max_tokens=output_len,
|
max_tokens=output_len,
|
||||||
))
|
))
|
||||||
|
|
||||||
start = time.perf_counter()
|
if not use_new_beam_search_impl:
|
||||||
llm.generate(prompts, sampling_params, use_tqdm=True)
|
start = time.perf_counter()
|
||||||
end = time.perf_counter()
|
llm.generate(prompts, sampling_params, use_tqdm=True)
|
||||||
|
end = time.perf_counter()
|
||||||
|
else:
|
||||||
|
assert use_beam_search
|
||||||
|
prompts = [prompt for prompt, _, _ in requests]
|
||||||
|
# output_len should be the same for all requests.
|
||||||
|
output_len = requests[0][2]
|
||||||
|
for prompt, input_len, _output_len in requests:
|
||||||
|
assert _output_len == output_len
|
||||||
|
start = time.perf_counter()
|
||||||
|
llm.beam_search(prompts,
|
||||||
|
beam_width=n,
|
||||||
|
max_tokens=output_len,
|
||||||
|
ignore_eos=True)
|
||||||
|
end = time.perf_counter()
|
||||||
return end - start
|
return end - start
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +206,6 @@ async def run_vllm_async(
|
|||||||
use_v2_block_manager=use_v2_block_manager,
|
use_v2_block_manager=use_v2_block_manager,
|
||||||
disable_async_output_proc=disable_async_output_proc,
|
disable_async_output_proc=disable_async_output_proc,
|
||||||
worker_use_ray=False,
|
worker_use_ray=False,
|
||||||
engine_use_ray=False,
|
|
||||||
disable_log_requests=True,
|
disable_log_requests=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -337,7 +351,7 @@ def main(args: argparse.Namespace):
|
|||||||
run_args.append(args.disable_frontend_multiprocessing)
|
run_args.append(args.disable_frontend_multiprocessing)
|
||||||
elapsed_time = uvloop.run(run_vllm_async(*run_args))
|
elapsed_time = uvloop.run(run_vllm_async(*run_args))
|
||||||
else:
|
else:
|
||||||
elapsed_time = run_vllm(*run_args)
|
elapsed_time = run_vllm(*run_args, args.use_new_beam_search_impl)
|
||||||
elif args.backend == "hf":
|
elif args.backend == "hf":
|
||||||
assert args.tensor_parallel_size == 1
|
assert args.tensor_parallel_size == 1
|
||||||
elapsed_time = run_hf(requests, args.model, tokenizer, args.n,
|
elapsed_time = run_hf(requests, args.model, tokenizer, args.n,
|
||||||
@@ -397,6 +411,7 @@ if __name__ == "__main__":
|
|||||||
default=1,
|
default=1,
|
||||||
help="Number of generated sequences per prompt.")
|
help="Number of generated sequences per prompt.")
|
||||||
parser.add_argument("--use-beam-search", action="store_true")
|
parser.add_argument("--use-beam-search", action="store_true")
|
||||||
|
parser.add_argument("--use-new-beam-search-impl", action="store_true")
|
||||||
parser.add_argument("--num-prompts",
|
parser.add_argument("--num-prompts",
|
||||||
type=int,
|
type=int,
|
||||||
default=1000,
|
default=1000,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import random
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
from vllm.model_executor.layers.layernorm import RMSNorm
|
from vllm.model_executor.layers.layernorm import RMSNorm
|
||||||
from vllm.utils import STR_DTYPE_TO_TORCH_DTYPE, FlexibleArgumentParser
|
from vllm.utils import (STR_DTYPE_TO_TORCH_DTYPE, FlexibleArgumentParser,
|
||||||
|
seed_everything)
|
||||||
|
|
||||||
|
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
@@ -16,10 +16,7 @@ def main(num_tokens: int,
|
|||||||
do_profile: bool = False,
|
do_profile: bool = False,
|
||||||
num_warmup_iters: int = 5,
|
num_warmup_iters: int = 5,
|
||||||
num_iters: int = 100) -> None:
|
num_iters: int = 100) -> None:
|
||||||
random.seed(seed)
|
seed_everything(seed)
|
||||||
torch.random.manual_seed(seed)
|
|
||||||
if torch.cuda.is_available():
|
|
||||||
torch.cuda.manual_seed(seed)
|
|
||||||
torch.set_default_device("cuda")
|
torch.set_default_device("cuda")
|
||||||
|
|
||||||
layer = RMSNorm(hidden_size).to(dtype=dtype)
|
layer = RMSNorm(hidden_size).to(dtype=dtype)
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import itertools
|
|||||||
import math
|
import math
|
||||||
import pickle as pkl
|
import pickle as pkl
|
||||||
import time
|
import time
|
||||||
from typing import Callable, Iterable, List, Tuple
|
from itertools import product
|
||||||
|
from typing import Callable, Iterable, List, Optional, Tuple
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
import torch
|
import torch
|
||||||
import torch.utils.benchmark as TBenchmark
|
import torch.utils.benchmark as TBenchmark
|
||||||
from torch.utils.benchmark import Measurement as TMeasurement
|
from torch.utils.benchmark import Measurement as TMeasurement
|
||||||
@@ -84,6 +86,10 @@ def loop_over_weights(
|
|||||||
fn(a, w_ref, w_q, w_s)
|
fn(a, w_ref, w_q, w_s)
|
||||||
|
|
||||||
|
|
||||||
|
_SWEEP_SCHEDULES_RESULTS: Optional[pd.DataFrame] = None
|
||||||
|
_SWEEP_SCHEDULES_RESULTS_CSV: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
def bench(atype: torch.dtype,
|
def bench(atype: torch.dtype,
|
||||||
wtype: ScalarType,
|
wtype: ScalarType,
|
||||||
group_size: int,
|
group_size: int,
|
||||||
@@ -94,6 +100,8 @@ def bench(atype: torch.dtype,
|
|||||||
sub_label: str,
|
sub_label: str,
|
||||||
benchmark_marlinv1: bool = True,
|
benchmark_marlinv1: bool = True,
|
||||||
sweep_schedules: bool = True) -> Iterable[TMeasurement]:
|
sweep_schedules: bool = True) -> Iterable[TMeasurement]:
|
||||||
|
global _SWEEP_SCHEDULES_RESULTS
|
||||||
|
|
||||||
a, weights = make_bench_tensors(atype, wtype, group_size, m, n, k)
|
a, weights = make_bench_tensors(atype, wtype, group_size, m, n, k)
|
||||||
sub_label += f", L={len(weights)}"
|
sub_label += f", L={len(weights)}"
|
||||||
|
|
||||||
@@ -163,6 +171,11 @@ def bench(atype: torch.dtype,
|
|||||||
best_schedule = None
|
best_schedule = None
|
||||||
schedules = ops.machete_supported_schedules(wtype)
|
schedules = ops.machete_supported_schedules(wtype)
|
||||||
for schedule in reversed(schedules):
|
for schedule in reversed(schedules):
|
||||||
|
schedule_M = int(schedule.split("_")[0].split("x")[1])
|
||||||
|
|
||||||
|
# Prune known bad schedules
|
||||||
|
if schedule_M >= 2 * max(m, 16) or schedule_M < m // 4:
|
||||||
|
continue
|
||||||
|
|
||||||
def run(a, _, w_q, w_s, schedule=schedule):
|
def run(a, _, w_q, w_s, schedule=schedule):
|
||||||
ops.machete_gemm(a,
|
ops.machete_gemm(a,
|
||||||
@@ -175,6 +188,20 @@ def bench(atype: torch.dtype,
|
|||||||
res = bench_fn(label, sub_label, "machete_best",
|
res = bench_fn(label, sub_label, "machete_best",
|
||||||
lambda: loop_over_weights(a, weights_machete, run))
|
lambda: loop_over_weights(a, weights_machete, run))
|
||||||
|
|
||||||
|
results_row = {
|
||||||
|
"M": m,
|
||||||
|
"K": k,
|
||||||
|
"N": n,
|
||||||
|
"group_size": group_size,
|
||||||
|
"schedule": schedule,
|
||||||
|
"median": res.median,
|
||||||
|
}
|
||||||
|
if _SWEEP_SCHEDULES_RESULTS is None:
|
||||||
|
_SWEEP_SCHEDULES_RESULTS = pd.DataFrame(
|
||||||
|
columns=results_row.keys())
|
||||||
|
_SWEEP_SCHEDULES_RESULTS.\
|
||||||
|
loc[len(_SWEEP_SCHEDULES_RESULTS)] = results_row
|
||||||
|
|
||||||
print(f" {res.median:5.5} ", schedule)
|
print(f" {res.median:5.5} ", schedule)
|
||||||
if not best or res.median < best.median:
|
if not best or res.median < best.median:
|
||||||
best = res
|
best = res
|
||||||
@@ -235,18 +262,22 @@ def run_square_bench(args):
|
|||||||
dim_sizes = list(
|
dim_sizes = list(
|
||||||
range(args.dim_start, args.dim_end + 1, args.dim_increment))
|
range(args.dim_start, args.dim_end + 1, args.dim_increment))
|
||||||
MKNs = list(zip(dim_sizes, dim_sizes, dim_sizes))
|
MKNs = list(zip(dim_sizes, dim_sizes, dim_sizes))
|
||||||
|
|
||||||
data = run(args.dtype, args.sweep_schedules, MKNs)
|
data = run(args.dtype, args.sweep_schedules, MKNs)
|
||||||
|
|
||||||
make_output(data, MKNs, f"square_bench-{args.dtype}")
|
make_output(data, MKNs, f"square_bench-{args.dtype}")
|
||||||
|
|
||||||
|
|
||||||
def run_range_bench(args):
|
def run_range_bench(args):
|
||||||
dim_sizes = list(range(args.dim_start, args.dim_end, args.dim_increment))
|
m_start, k_start, n_start = [int(x) for x in args.dim_start.split(",")]
|
||||||
n = len(dim_sizes)
|
m_end, k_end, n_end = [int(x) for x in args.dim_end.split(",")]
|
||||||
Ms = [args.m_constant] * n if args.m_constant is not None else dim_sizes
|
m_increment, k_increment, n_increment = \
|
||||||
Ks = [args.k_constant] * n if args.k_constant is not None else dim_sizes
|
[int(x) for x in args.dim_increment.split(",")]
|
||||||
Ns = [args.n_constant] * n if args.n_constant is not None else dim_sizes
|
Ms = list(range(m_start, m_end + 1, m_increment))
|
||||||
MKNs = list(zip(Ms, Ks, Ns))
|
Ks = list(range(k_start, k_end + 1, k_increment))
|
||||||
|
Ns = list(range(n_start, n_end + 1, n_increment))
|
||||||
|
MKNs = list(product(Ms, Ks, Ns))
|
||||||
|
|
||||||
data = run(args.dtype, args.sweep_schedules, MKNs)
|
data = run(args.dtype, args.sweep_schedules, MKNs)
|
||||||
|
|
||||||
make_output(data, MKNs, f"range_bench-{args.dtype}")
|
make_output(data, MKNs, f"range_bench-{args.dtype}")
|
||||||
@@ -333,6 +364,9 @@ Benchmark Machete GEMM.
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help="Run a sweep over all supported schedules",
|
help="Run a sweep over all supported schedules",
|
||||||
)
|
)
|
||||||
|
parser.add_argument("--sweep-csv-out",
|
||||||
|
help="CSV to store sweep results",
|
||||||
|
default="sch_sweep_results.csv")
|
||||||
subparsers = parser.add_subparsers(dest="cmd", required=True)
|
subparsers = parser.add_subparsers(dest="cmd", required=True)
|
||||||
|
|
||||||
square_parser = subparsers.add_parser("square_bench")
|
square_parser = subparsers.add_parser("square_bench")
|
||||||
@@ -342,12 +376,21 @@ Benchmark Machete GEMM.
|
|||||||
square_parser.set_defaults(func=run_square_bench)
|
square_parser.set_defaults(func=run_square_bench)
|
||||||
|
|
||||||
range_parser = subparsers.add_parser("range_bench")
|
range_parser = subparsers.add_parser("range_bench")
|
||||||
range_parser.add_argument("--dim-start", type=int, required=True)
|
range_parser.add_argument(
|
||||||
range_parser.add_argument("--dim-end", type=int, required=True)
|
"--dim-start",
|
||||||
range_parser.add_argument("--dim-increment", type=int, required=True)
|
type=str,
|
||||||
range_parser.add_argument("--m-constant", type=int, default=None)
|
required=True,
|
||||||
range_parser.add_argument("--n-constant", type=int, default=None)
|
help="Start value for M,K,N as common separated list")
|
||||||
range_parser.add_argument("--k-constant", type=int, default=None)
|
range_parser.add_argument(
|
||||||
|
"--dim-end",
|
||||||
|
type=str,
|
||||||
|
required=True,
|
||||||
|
help="End value (inclusive) for M,K,N as common separated list")
|
||||||
|
range_parser.add_argument(
|
||||||
|
"--dim-increment",
|
||||||
|
type=str,
|
||||||
|
required=True,
|
||||||
|
help="Increment value for M,K,N as common separated list")
|
||||||
range_parser.set_defaults(func=run_range_bench)
|
range_parser.set_defaults(func=run_range_bench)
|
||||||
|
|
||||||
model_parser = subparsers.add_parser("model_bench")
|
model_parser = subparsers.add_parser("model_bench")
|
||||||
@@ -369,4 +412,9 @@ Benchmark Machete GEMM.
|
|||||||
model_parser.set_defaults(func=run_model_bench)
|
model_parser.set_defaults(func=run_model_bench)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
_SWEEP_SCHEDULES_RESULTS_CSV = args.sweep_csv_out
|
||||||
args.func(args)
|
args.func(args)
|
||||||
|
|
||||||
|
if _SWEEP_SCHEDULES_RESULTS is not None:
|
||||||
|
_SWEEP_SCHEDULES_RESULTS.to_csv(_SWEEP_SCHEDULES_RESULTS_CSV)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from ray.experimental.tqdm_ray import tqdm
|
|||||||
from transformers import AutoConfig
|
from transformers import AutoConfig
|
||||||
|
|
||||||
from vllm.model_executor.layers.fused_moe.fused_moe import *
|
from vllm.model_executor.layers.fused_moe.fused_moe import *
|
||||||
from vllm.utils import FlexibleArgumentParser
|
from vllm.utils import FlexibleArgumentParser, seed_everything
|
||||||
|
|
||||||
|
|
||||||
class BenchmarkConfig(TypedDict):
|
class BenchmarkConfig(TypedDict):
|
||||||
@@ -166,7 +166,7 @@ class BenchmarkWorker:
|
|||||||
|
|
||||||
def __init__(self, seed: int) -> None:
|
def __init__(self, seed: int) -> None:
|
||||||
torch.set_default_device("cuda")
|
torch.set_default_device("cuda")
|
||||||
torch.cuda.manual_seed_all(seed)
|
seed_everything(seed)
|
||||||
self.seed = seed
|
self.seed = seed
|
||||||
|
|
||||||
def benchmark(
|
def benchmark(
|
||||||
@@ -180,7 +180,7 @@ class BenchmarkWorker:
|
|||||||
use_fp8_w8a8: bool,
|
use_fp8_w8a8: bool,
|
||||||
use_int8_w8a16: bool,
|
use_int8_w8a16: bool,
|
||||||
) -> Tuple[Dict[str, int], float]:
|
) -> Tuple[Dict[str, int], float]:
|
||||||
torch.cuda.manual_seed_all(self.seed)
|
seed_everything(self.seed)
|
||||||
dtype_str = get_config_dtype_str(dtype,
|
dtype_str = get_config_dtype_str(dtype,
|
||||||
use_int8_w8a16=use_int8_w8a16,
|
use_int8_w8a16=use_int8_w8a16,
|
||||||
use_fp8_w8a8=use_fp8_w8a8)
|
use_fp8_w8a8=use_fp8_w8a8)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import torch
|
|||||||
|
|
||||||
from vllm import _custom_ops as ops
|
from vllm import _custom_ops as ops
|
||||||
from vllm.utils import (STR_DTYPE_TO_TORCH_DTYPE, FlexibleArgumentParser,
|
from vllm.utils import (STR_DTYPE_TO_TORCH_DTYPE, FlexibleArgumentParser,
|
||||||
create_kv_caches_with_random)
|
create_kv_caches_with_random, seed_everything)
|
||||||
|
|
||||||
NUM_BLOCKS = 1024
|
NUM_BLOCKS = 1024
|
||||||
PARTITION_SIZE = 512
|
PARTITION_SIZE = 512
|
||||||
@@ -28,10 +28,7 @@ def main(
|
|||||||
device: str = "cuda",
|
device: str = "cuda",
|
||||||
kv_cache_dtype: Optional[str] = None,
|
kv_cache_dtype: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
random.seed(seed)
|
seed_everything(seed)
|
||||||
torch.random.manual_seed(seed)
|
|
||||||
if torch.cuda.is_available():
|
|
||||||
torch.cuda.manual_seed(seed)
|
|
||||||
|
|
||||||
scale = float(1.0 / (head_size**0.5))
|
scale = float(1.0 / (head_size**0.5))
|
||||||
query = torch.empty(num_seqs,
|
query = torch.empty(num_seqs,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import random
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
|
|
||||||
from vllm import _custom_ops as ops
|
from vllm import _custom_ops as ops
|
||||||
from vllm.utils import STR_DTYPE_TO_TORCH_DTYPE, FlexibleArgumentParser
|
from vllm.utils import (STR_DTYPE_TO_TORCH_DTYPE, FlexibleArgumentParser,
|
||||||
|
seed_everything)
|
||||||
|
|
||||||
|
|
||||||
@torch.inference_mode()
|
@torch.inference_mode()
|
||||||
@@ -17,10 +17,7 @@ def main(num_tokens: int,
|
|||||||
do_profile: bool = False,
|
do_profile: bool = False,
|
||||||
num_warmup_iters: int = 5,
|
num_warmup_iters: int = 5,
|
||||||
num_iters: int = 100) -> None:
|
num_iters: int = 100) -> None:
|
||||||
random.seed(seed)
|
seed_everything(seed)
|
||||||
torch.random.manual_seed(seed)
|
|
||||||
if torch.cuda.is_available():
|
|
||||||
torch.cuda.manual_seed(seed)
|
|
||||||
torch.set_default_device("cuda")
|
torch.set_default_device("cuda")
|
||||||
|
|
||||||
x = torch.randn(num_tokens, hidden_size, dtype=dtype)
|
x = torch.randn(num_tokens, hidden_size, dtype=dtype)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import torch
|
|||||||
|
|
||||||
from vllm.model_executor.layers.rotary_embedding import (RotaryEmbedding,
|
from vllm.model_executor.layers.rotary_embedding import (RotaryEmbedding,
|
||||||
get_rope)
|
get_rope)
|
||||||
from vllm.utils import FlexibleArgumentParser
|
from vllm.utils import FlexibleArgumentParser, seed_everything
|
||||||
|
|
||||||
|
|
||||||
def benchmark_rope_kernels_multi_lora(
|
def benchmark_rope_kernels_multi_lora(
|
||||||
@@ -22,9 +22,7 @@ def benchmark_rope_kernels_multi_lora(
|
|||||||
max_position: int = 8192,
|
max_position: int = 8192,
|
||||||
base: int = 10000,
|
base: int = 10000,
|
||||||
) -> None:
|
) -> None:
|
||||||
torch.random.manual_seed(seed)
|
seed_everything(seed)
|
||||||
if torch.cuda.is_available():
|
|
||||||
torch.cuda.manual_seed(seed)
|
|
||||||
torch.set_default_device(device)
|
torch.set_default_device(device)
|
||||||
if rotary_dim is None:
|
if rotary_dim is None:
|
||||||
rotary_dim = head_size
|
rotary_dim = head_size
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ if __name__ == "__main__":
|
|||||||
rows = int(math.ceil(len(results) / 2))
|
rows = int(math.ceil(len(results) / 2))
|
||||||
fig, axs = plt.subplots(rows, 2, figsize=(12, 5 * rows))
|
fig, axs = plt.subplots(rows, 2, figsize=(12, 5 * rows))
|
||||||
axs = axs.flatten()
|
axs = axs.flatten()
|
||||||
axs_idx = 0
|
for axs_idx, (shape, data) in enumerate(results.items()):
|
||||||
for shape, data in results.items():
|
|
||||||
plt.sca(axs[axs_idx])
|
plt.sca(axs[axs_idx])
|
||||||
df = pd.DataFrame(data)
|
df = pd.DataFrame(data)
|
||||||
sns.lineplot(data=df,
|
sns.lineplot(data=df,
|
||||||
@@ -59,6 +58,5 @@ if __name__ == "__main__":
|
|||||||
palette="Dark2")
|
palette="Dark2")
|
||||||
plt.title(f"Shape: {shape}")
|
plt.title(f"Shape: {shape}")
|
||||||
plt.ylabel("time (median, s)")
|
plt.ylabel("time (median, s)")
|
||||||
axs_idx += 1
|
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
plt.savefig("graph_machete_bench.pdf")
|
plt.savefig("graph_machete_bench.pdf")
|
||||||
|
|||||||
1
benchmarks/kernels/requirements.txt
Normal file
1
benchmarks/kernels/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pandas
|
||||||
@@ -120,4 +120,3 @@ define_gpu_extension_target(
|
|||||||
)
|
)
|
||||||
|
|
||||||
message(STATUS "Enabling C extension.")
|
message(STATUS "Enabling C extension.")
|
||||||
add_dependencies(default _C)
|
|
||||||
|
|||||||
@@ -350,18 +350,19 @@ function (define_gpu_extension_target GPU_MOD_NAME)
|
|||||||
target_include_directories(${GPU_MOD_NAME} PRIVATE csrc
|
target_include_directories(${GPU_MOD_NAME} PRIVATE csrc
|
||||||
${GPU_INCLUDE_DIRECTORIES})
|
${GPU_INCLUDE_DIRECTORIES})
|
||||||
|
|
||||||
# TODO: is torch_python_LIBRARY needed?
|
target_link_libraries(${GPU_MOD_NAME} PRIVATE torch ${GPU_LIBRARIES})
|
||||||
target_link_libraries(${GPU_MOD_NAME} PRIVATE torch ${torch_python_LIBRARY}
|
|
||||||
${GPU_LIBRARIES})
|
|
||||||
|
|
||||||
# Don't use `TORCH_LIBRARIES` for CUDA since it pulls in a bunch of
|
# Don't use `TORCH_LIBRARIES` for CUDA since it pulls in a bunch of
|
||||||
# dependencies that are not necessary and may not be installed.
|
# dependencies that are not necessary and may not be installed.
|
||||||
if (GPU_LANGUAGE STREQUAL "CUDA")
|
if (GPU_LANGUAGE STREQUAL "CUDA")
|
||||||
|
if ("${CUDA_CUDA_LIB}" STREQUAL "")
|
||||||
|
set(CUDA_CUDA_LIB "${CUDA_CUDA_LIBRARY}")
|
||||||
|
endif()
|
||||||
target_link_libraries(${GPU_MOD_NAME} PRIVATE ${CUDA_CUDA_LIB}
|
target_link_libraries(${GPU_MOD_NAME} PRIVATE ${CUDA_CUDA_LIB}
|
||||||
${CUDA_LIBRARIES})
|
${CUDA_LIBRARIES})
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${GPU_MOD_NAME} PRIVATE ${TORCH_LIBRARIES})
|
target_link_libraries(${GPU_MOD_NAME} PRIVATE ${TORCH_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(TARGETS ${GPU_MOD_NAME} LIBRARY DESTINATION ${GPU_DESTINATION})
|
install(TARGETS ${GPU_MOD_NAME} LIBRARY DESTINATION ${GPU_DESTINATION} COMPONENT ${GPU_MOD_NAME})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|||||||
@@ -285,9 +285,14 @@ def summarize_vllm_build_flags():
|
|||||||
|
|
||||||
|
|
||||||
def get_gpu_topo(run_lambda):
|
def get_gpu_topo(run_lambda):
|
||||||
|
output = None
|
||||||
|
|
||||||
if get_platform() == 'linux':
|
if get_platform() == 'linux':
|
||||||
return run_and_read_all(run_lambda, 'nvidia-smi topo -m')
|
output = run_and_read_all(run_lambda, 'nvidia-smi topo -m')
|
||||||
return None
|
if output is None:
|
||||||
|
output = run_and_read_all(run_lambda, 'rocm-smi --showtopo')
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
# example outputs of CPU infos
|
# example outputs of CPU infos
|
||||||
|
|||||||
@@ -257,11 +257,13 @@ void int8_scaled_mm(torch::Tensor& c, // [M, OC], row-major
|
|||||||
// static-per-tensor quantization.
|
// static-per-tensor quantization.
|
||||||
void static_scaled_int8_quant(torch::Tensor& out, // [..., hidden_size]
|
void static_scaled_int8_quant(torch::Tensor& out, // [..., hidden_size]
|
||||||
const torch::Tensor& input, // [..., hidden_size]
|
const torch::Tensor& input, // [..., hidden_size]
|
||||||
const torch::Tensor& scale) {
|
const torch::Tensor& scale,
|
||||||
|
c10::optional<torch::Tensor> const& azp) {
|
||||||
CPU_KERNEL_GUARD_IN(static_scaled_int8_quant)
|
CPU_KERNEL_GUARD_IN(static_scaled_int8_quant)
|
||||||
TORCH_CHECK(input.is_contiguous());
|
TORCH_CHECK(input.is_contiguous());
|
||||||
TORCH_CHECK(out.is_contiguous());
|
TORCH_CHECK(out.is_contiguous());
|
||||||
TORCH_CHECK(scale.numel() == 1);
|
TORCH_CHECK(scale.numel() == 1);
|
||||||
|
TORCH_CHECK(!azp.has_value(), "Zero point is not supported on CPU.");
|
||||||
|
|
||||||
const int hidden_size = input.size(-1);
|
const int hidden_size = input.size(-1);
|
||||||
const int num_tokens = input.numel() / hidden_size;
|
const int num_tokens = input.numel() / hidden_size;
|
||||||
@@ -277,11 +279,12 @@ void static_scaled_int8_quant(torch::Tensor& out, // [..., hidden_size]
|
|||||||
void dynamic_scaled_int8_quant(
|
void dynamic_scaled_int8_quant(
|
||||||
torch::Tensor& out, // [..., hidden_size]
|
torch::Tensor& out, // [..., hidden_size]
|
||||||
const torch::Tensor& input, // [..., hidden_size]
|
const torch::Tensor& input, // [..., hidden_size]
|
||||||
torch::Tensor& scale // [..., 1]
|
torch::Tensor& scale, // [..., 1]
|
||||||
) {
|
c10::optional<torch::Tensor> const& azp) {
|
||||||
CPU_KERNEL_GUARD_IN(dynamic_scaled_int8_quant)
|
CPU_KERNEL_GUARD_IN(dynamic_scaled_int8_quant)
|
||||||
TORCH_CHECK(input.is_contiguous());
|
TORCH_CHECK(input.is_contiguous());
|
||||||
TORCH_CHECK(out.is_contiguous());
|
TORCH_CHECK(out.is_contiguous());
|
||||||
|
TORCH_CHECK(!azp.has_value(), "Zero point is not supported on CPU.");
|
||||||
|
|
||||||
int const hidden_size = input.size(-1);
|
int const hidden_size = input.size(-1);
|
||||||
int const num_tokens = input.numel() / hidden_size;
|
int const num_tokens = input.numel() / hidden_size;
|
||||||
|
|||||||
@@ -94,13 +94,14 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
|
|||||||
#ifdef __AVX512F__
|
#ifdef __AVX512F__
|
||||||
// Compute int8 quantized tensor for given scaling factor.
|
// Compute int8 quantized tensor for given scaling factor.
|
||||||
ops.def(
|
ops.def(
|
||||||
"static_scaled_int8_quant(Tensor! out, Tensor input, Tensor scale) -> "
|
"static_scaled_int8_quant(Tensor! out, Tensor input, Tensor scale,"
|
||||||
"()");
|
"Tensor? azp) -> ()");
|
||||||
ops.impl("static_scaled_int8_quant", torch::kCPU, &static_scaled_int8_quant);
|
ops.impl("static_scaled_int8_quant", torch::kCPU, &static_scaled_int8_quant);
|
||||||
|
|
||||||
// Compute int8 quantized tensor and scaling factor
|
// Compute int8 quantized tensor and scaling factor
|
||||||
ops.def(
|
ops.def(
|
||||||
"dynamic_scaled_int8_quant(Tensor! out, Tensor input, Tensor! scale) -> "
|
"dynamic_scaled_int8_quant(Tensor! out, Tensor input, Tensor! scale, "
|
||||||
"()");
|
"Tensor!? azp) -> ()");
|
||||||
ops.impl("dynamic_scaled_int8_quant", torch::kCPU,
|
ops.impl("dynamic_scaled_int8_quant", torch::kCPU,
|
||||||
&dynamic_scaled_int8_quant);
|
&dynamic_scaled_int8_quant);
|
||||||
// W8A8 GEMM, supporting symmetric per-tensor or per-row/column
|
// W8A8 GEMM, supporting symmetric per-tensor or per-row/column
|
||||||
|
|||||||
@@ -55,18 +55,6 @@ bool _is_weak_contiguous(torch::Tensor& t) {
|
|||||||
t.numel() * t.element_size());
|
t.numel() * t.element_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_custom_ar(torch::Tensor& inp, int64_t max_size, int64_t world_size,
|
|
||||||
bool full_nvlink) {
|
|
||||||
auto inp_size = inp.numel() * inp.element_size();
|
|
||||||
// custom allreduce requires input byte size to be multiples of 16
|
|
||||||
if (inp_size % 16 != 0) return false;
|
|
||||||
if (!_is_weak_contiguous(inp)) return false;
|
|
||||||
if (world_size == 2 || full_nvlink) return inp_size <= max_size;
|
|
||||||
// for 4 or more non NVLink-capable GPUs, custom allreduce provides little
|
|
||||||
// performance improvement over NCCL.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _all_reduce(fptr_t _fa, torch::Tensor& inp, torch::Tensor& out,
|
void _all_reduce(fptr_t _fa, torch::Tensor& inp, torch::Tensor& out,
|
||||||
cudaStream_t stream) {
|
cudaStream_t stream) {
|
||||||
auto fa = reinterpret_cast<vllm::CustomAllreduce*>(_fa);
|
auto fa = reinterpret_cast<vllm::CustomAllreduce*>(_fa);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <cuda_runtime.h>
|
#include <cuda_runtime.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <array>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -23,17 +24,23 @@
|
|||||||
|
|
||||||
namespace vllm {
|
namespace vllm {
|
||||||
|
|
||||||
constexpr int kMaxBlocks = 64;
|
constexpr int kMaxBlocks = 36;
|
||||||
// note: we don't want to use atomics for signals because peer atomics are no
|
// Counter may overflow, but it's fine since unsigned int overflow is
|
||||||
// supported on PCIe links
|
// well-defined behavior.
|
||||||
|
using FlagType = uint32_t;
|
||||||
struct Signal {
|
struct Signal {
|
||||||
alignas(128) uint32_t start[kMaxBlocks][8];
|
alignas(128) FlagType self_counter[kMaxBlocks][8];
|
||||||
alignas(128) uint32_t end[kMaxBlocks][8];
|
// Two sets of peer counters are needed for two syncs. The reason is that
|
||||||
|
// it's possible for peer GPU block to arrive at the second sync point while
|
||||||
|
// the current GPU block haven't passed the first sync point. Thus, peer GPU
|
||||||
|
// may write counter+1 while current GPU is busy waiting for counter. We use
|
||||||
|
// alternating counter array to avoid this possibility.
|
||||||
|
alignas(128) FlagType peer_counter[2][kMaxBlocks][8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __align__(16) RankData { const void* __restrict__ ptrs[8]; };
|
struct __align__(16) RankData { const void* __restrict__ ptrs[8]; };
|
||||||
|
|
||||||
struct __align__(16) RankSignals { volatile Signal* signals[8]; };
|
struct __align__(16) RankSignals { Signal* signals[8]; };
|
||||||
|
|
||||||
// like std::array, but aligned
|
// like std::array, but aligned
|
||||||
template <typename T, int sz>
|
template <typename T, int sz>
|
||||||
@@ -123,47 +130,71 @@ DINLINE O downcast(array_t<float, O::size> val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is meant to be used as the first synchronization in the all
|
static DINLINE void st_flag_release(FlagType* flag_addr, FlagType flag) {
|
||||||
// reduce kernel. Thus, it doesn't need to make any visibility guarantees for
|
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
|
||||||
// prior memory accesses. Note: volatile writes will not be reordered against
|
asm volatile("st.release.sys.global.u32 [%1], %0;" ::"r"(flag),
|
||||||
// other volatile writes.
|
"l"(flag_addr));
|
||||||
template <int ngpus>
|
#else
|
||||||
DINLINE void start_sync(const RankSignals& sg, volatile Signal* self_sg,
|
asm volatile("membar.sys; st.volatile.global.u32 [%1], %0;" ::"r"(flag),
|
||||||
int rank) {
|
"l"(flag_addr));
|
||||||
if (threadIdx.x < ngpus) {
|
#endif
|
||||||
// reset flag for next time
|
|
||||||
self_sg->end[blockIdx.x][threadIdx.x] = 0;
|
|
||||||
// simultaneously write to the corresponding flag of all ranks.
|
|
||||||
// Latency = 1 p2p write
|
|
||||||
sg.signals[threadIdx.x]->start[blockIdx.x][rank] = 1;
|
|
||||||
// wait until we got true from all ranks
|
|
||||||
while (!self_sg->start[blockIdx.x][threadIdx.x]);
|
|
||||||
}
|
|
||||||
__syncthreads();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is meant to be used as the second or the final synchronization
|
static DINLINE FlagType ld_flag_acquire(FlagType* flag_addr) {
|
||||||
// barrier in the all reduce kernel. If it's the final synchronization barrier,
|
FlagType flag;
|
||||||
// we don't need to make any visibility guarantees for prior memory accesses.
|
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
|
||||||
template <int ngpus, bool final_sync = false>
|
asm volatile("ld.acquire.sys.global.u32 %0, [%1];"
|
||||||
DINLINE void end_sync(const RankSignals& sg, volatile Signal* self_sg,
|
: "=r"(flag)
|
||||||
int rank) {
|
: "l"(flag_addr));
|
||||||
__syncthreads();
|
#else
|
||||||
// eliminate the case that prior writes are not visible after signals become
|
asm volatile("ld.volatile.global.u32 %0, [%1]; membar.gl;"
|
||||||
// visible. Note that I did not managed to make this happen through a lot of
|
: "=r"(flag)
|
||||||
// testing. Might be the case that hardware provides stronger guarantee than
|
: "l"(flag_addr));
|
||||||
// the memory model.
|
#endif
|
||||||
if constexpr (!final_sync) __threadfence_system();
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DINLINE void st_flag_volatile(FlagType* flag_addr, FlagType flag) {
|
||||||
|
asm volatile("st.volatile.global.u32 [%1], %0;" ::"r"(flag), "l"(flag_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static DINLINE FlagType ld_flag_volatile(FlagType* flag_addr) {
|
||||||
|
FlagType flag;
|
||||||
|
asm volatile("ld.volatile.global.u32 %0, [%1];"
|
||||||
|
: "=r"(flag)
|
||||||
|
: "l"(flag_addr));
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is_start: whether this is the very first synchronization barrier.
|
||||||
|
// need_fence: whether a memory fence is needed. If true, a release-acquire
|
||||||
|
// semantic is used to enforce memory access order before and after this
|
||||||
|
// barrier.
|
||||||
|
template <int ngpus, bool is_start, bool need_fence = false>
|
||||||
|
DINLINE void multi_gpu_barrier(const RankSignals& sg, Signal* self_sg,
|
||||||
|
int rank) {
|
||||||
|
if constexpr (!is_start) __syncthreads();
|
||||||
|
static_assert(
|
||||||
|
!(is_start && need_fence)); // Start barrier shouldn't need fence.
|
||||||
if (threadIdx.x < ngpus) {
|
if (threadIdx.x < ngpus) {
|
||||||
// reset flag for next time
|
// Increment the counter. Technically we only need one counter, but we use
|
||||||
self_sg->start[blockIdx.x][threadIdx.x] = 0;
|
// multiple per block to eliminate the need to share the counter via smem.
|
||||||
// simultaneously write to the corresponding flag of all ranks.
|
auto val = self_sg->self_counter[blockIdx.x][threadIdx.x] += 1;
|
||||||
// Latency = 1 p2p write
|
// Write the expected counter value to peer and wait for correct value from
|
||||||
sg.signals[threadIdx.x]->end[blockIdx.x][rank] = 1;
|
// peer.
|
||||||
// wait until we got true from all ranks
|
auto peer_counter_ptr =
|
||||||
while (!self_sg->end[blockIdx.x][threadIdx.x]);
|
&sg.signals[threadIdx.x]->peer_counter[val % 2][blockIdx.x][rank];
|
||||||
|
auto self_counter_ptr =
|
||||||
|
&self_sg->peer_counter[val % 2][blockIdx.x][threadIdx.x];
|
||||||
|
if constexpr (need_fence) {
|
||||||
|
st_flag_release(peer_counter_ptr, val);
|
||||||
|
while (ld_flag_acquire(self_counter_ptr) != val);
|
||||||
|
} else {
|
||||||
|
st_flag_volatile(peer_counter_ptr, val);
|
||||||
|
while (ld_flag_volatile(self_counter_ptr) != val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if constexpr (!final_sync) __syncthreads();
|
if constexpr (is_start || need_fence) __syncthreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P, int ngpus, typename A>
|
template <typename P, int ngpus, typename A>
|
||||||
@@ -178,33 +209,31 @@ DINLINE P packed_reduce(const P* ptrs[], int idx) {
|
|||||||
|
|
||||||
template <typename T, int ngpus>
|
template <typename T, int ngpus>
|
||||||
__global__ void __launch_bounds__(512, 1)
|
__global__ void __launch_bounds__(512, 1)
|
||||||
cross_device_reduce_1stage(RankData* _dp, RankSignals sg,
|
cross_device_reduce_1stage(RankData* _dp, RankSignals sg, Signal* self_sg,
|
||||||
volatile Signal* self_sg, T* __restrict__ result,
|
T* __restrict__ result, int rank, int size) {
|
||||||
int rank, int size) {
|
|
||||||
using P = typename packed_t<T>::P;
|
using P = typename packed_t<T>::P;
|
||||||
using A = typename packed_t<T>::A;
|
using A = typename packed_t<T>::A;
|
||||||
// note: we don't reorder the address so the accumulation order is the same
|
// note: we don't reorder the address so the accumulation order is the same
|
||||||
// for all ranks, ensuring bitwise identical results
|
// for all ranks, ensuring bitwise identical results
|
||||||
auto dp = *_dp;
|
auto dp = *_dp;
|
||||||
start_sync<ngpus>(sg, self_sg, rank);
|
multi_gpu_barrier<ngpus, true>(sg, self_sg, rank);
|
||||||
// do the actual reduction
|
// do the actual reduction
|
||||||
for (int idx = blockIdx.x * blockDim.x + threadIdx.x; idx < size;
|
for (int idx = blockIdx.x * blockDim.x + threadIdx.x; idx < size;
|
||||||
idx += gridDim.x * blockDim.x) {
|
idx += gridDim.x * blockDim.x) {
|
||||||
((P*)result)[idx] = packed_reduce<P, ngpus, A>((const P**)&dp.ptrs[0], idx);
|
((P*)result)[idx] = packed_reduce<P, ngpus, A>((const P**)&dp.ptrs[0], idx);
|
||||||
}
|
}
|
||||||
end_sync<ngpus, true>(sg, self_sg, rank);
|
multi_gpu_barrier<ngpus, false>(sg, self_sg, rank);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
DINLINE P* get_tmp_buf(volatile Signal* sg) {
|
DINLINE P* get_tmp_buf(Signal* sg) {
|
||||||
return (P*)(((Signal*)sg) + 1);
|
return (P*)(((Signal*)sg) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int ngpus>
|
template <typename T, int ngpus>
|
||||||
__global__ void __launch_bounds__(512, 1)
|
__global__ void __launch_bounds__(512, 1)
|
||||||
cross_device_reduce_2stage(RankData* _dp, RankSignals sg,
|
cross_device_reduce_2stage(RankData* _dp, RankSignals sg, Signal* self_sg,
|
||||||
volatile Signal* self_sg, T* __restrict__ result,
|
T* __restrict__ result, int rank, int size) {
|
||||||
int rank, int size) {
|
|
||||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||||
int stride = gridDim.x * blockDim.x;
|
int stride = gridDim.x * blockDim.x;
|
||||||
using P = typename packed_t<T>::P;
|
using P = typename packed_t<T>::P;
|
||||||
@@ -222,12 +251,12 @@ __global__ void __launch_bounds__(512, 1)
|
|||||||
tmps[i] = get_tmp_buf<P>(sg.signals[target]);
|
tmps[i] = get_tmp_buf<P>(sg.signals[target]);
|
||||||
}
|
}
|
||||||
auto tmp_out = tmps[0];
|
auto tmp_out = tmps[0];
|
||||||
start_sync<ngpus>(sg, self_sg, rank);
|
multi_gpu_barrier<ngpus, true>(sg, self_sg, rank);
|
||||||
// stage 1: reduce scatter
|
// stage 1: reduce scatter
|
||||||
for (int idx = start + tid; idx < end; idx += stride) {
|
for (int idx = start + tid; idx < end; idx += stride) {
|
||||||
tmp_out[idx - start] = packed_reduce<P, ngpus, A>(ptrs, idx);
|
tmp_out[idx - start] = packed_reduce<P, ngpus, A>(ptrs, idx);
|
||||||
}
|
}
|
||||||
end_sync<ngpus>(sg, self_sg, rank);
|
multi_gpu_barrier<ngpus, false, true>(sg, self_sg, rank);
|
||||||
|
|
||||||
// stage 2: allgather. Note: it's important to match the tid between
|
// stage 2: allgather. Note: it's important to match the tid between
|
||||||
// the two stages, because visibility across devices is only guaranteed
|
// the two stages, because visibility across devices is only guaranteed
|
||||||
@@ -437,6 +466,8 @@ class CustomAllreduce {
|
|||||||
#define KL(ngpus, name) \
|
#define KL(ngpus, name) \
|
||||||
name<T, ngpus><<<blocks, threads, 0, stream>>>(ptrs, sg_, self_sg_, output, \
|
name<T, ngpus><<<blocks, threads, 0, stream>>>(ptrs, sg_, self_sg_, output, \
|
||||||
rank_, size);
|
rank_, size);
|
||||||
|
// TODO(hanzhi713): Threshold is different for A100 and H100.
|
||||||
|
// Add per device threshold.
|
||||||
#define REDUCE_CASE(ngpus) \
|
#define REDUCE_CASE(ngpus) \
|
||||||
case ngpus: { \
|
case ngpus: { \
|
||||||
if (world_size_ == 2) { \
|
if (world_size_ == 2) { \
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
/**
|
/**
|
||||||
* This is a standalone test for custom allreduce.
|
* This is a standalone test for custom allreduce.
|
||||||
* To compile, make sure you have MPI and NCCL installed in your system.
|
* To compile, make sure you have MPI and NCCL installed in your system.
|
||||||
* export MPI_HOME=XXX
|
* export MPI_HOME=xxx
|
||||||
* nvcc -O2 -arch=native -std=c++17 custom_all_reduce_test.cu -o
|
* nvcc -O2 -arch=native -std=c++17 custom_all_reduce_test.cu -o
|
||||||
* custom_all_reduce_test -lnccl -I${MPI_HOME}/include -lmpi
|
* custom_all_reduce_test -lnccl -I${MPI_HOME} -lmpi
|
||||||
*
|
*
|
||||||
* Warning: this C++ test is not designed to be very readable and was used
|
* Warning: this C++ test is not designed to be very readable and was used
|
||||||
* during the rapid prototyping process.
|
* during the rapid prototyping process.
|
||||||
*
|
*
|
||||||
* To run:
|
* To run:
|
||||||
* mpirun -np 8 ./custom_all_reduce_test
|
* mpirun --allow-run-as-root -np 8 ./custom_all_reduce_test
|
||||||
*/
|
*/
|
||||||
#include <cuda.h>
|
#include <cuda.h>
|
||||||
#include <curand_kernel.h>
|
#include <curand_kernel.h>
|
||||||
@@ -44,7 +44,14 @@
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
__global__ void dummy_kernel() {
|
__global__ void dummy_kernel() {
|
||||||
|
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
|
||||||
for (int i = 0; i < 100; i++) __nanosleep(1000000); // 100ms
|
for (int i = 0; i < 100; i++) __nanosleep(1000000); // 100ms
|
||||||
|
#else
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
long long int start = clock64();
|
||||||
|
while (clock64() - start < 150000000); // approximately 98.4ms on P40
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -302,15 +309,19 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
bool performance_test = true;
|
bool performance_test = true;
|
||||||
cudaProfilerStart();
|
cudaProfilerStart();
|
||||||
// for (int threads : {256, 512}) {
|
// Uncomment to scan through different block size configs.
|
||||||
|
// for (int threads : {256, 512, 1024}) {
|
||||||
// for (int block_limit = 16; block_limit < 112; block_limit += 4) {
|
// for (int block_limit = 16; block_limit < 112; block_limit += 4) {
|
||||||
// run<half>(myRank, nRanks, comm, threads, block_limit, 4096 * 1024);
|
// run<half>(myRank, nRanks, comm, threads, block_limit, 1024 * 1024,
|
||||||
|
// performance_test);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
// Scan through different sizes to test performance.
|
||||||
for (int sz = 512; sz <= (8 << 20); sz *= 2) {
|
for (int sz = 512; sz <= (8 << 20); sz *= 2) {
|
||||||
run<half>(myRank, nRanks, comm, 512, 36, sz + 8 * 47, performance_test);
|
run<half>(myRank, nRanks, comm, 512, 36, sz + 8 * 47, performance_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
cudaProfilerStop();
|
cudaProfilerStop();
|
||||||
|
MPICHECK(MPI_Finalize());
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,13 @@ static inline auto make_cute_layout(torch::Tensor const& tensor,
|
|||||||
name, ".stride(", idx, ") to be ", StrideEle::value);
|
name, ".stride(", idx, ") to be ", StrideEle::value);
|
||||||
return StrideEle{};
|
return StrideEle{};
|
||||||
} else {
|
} else {
|
||||||
return tensor.stride(idx);
|
if (tensor.size(idx) == 1) {
|
||||||
|
// use 0 stride for dim with size 1, this is easier for
|
||||||
|
// cute/cutlass to optimize (helps the TMA code flatten dims)
|
||||||
|
return StrideEle{0};
|
||||||
|
} else {
|
||||||
|
return tensor.stride(idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Extra strides are assumed to be 0 or 1
|
// Extra strides are assumed to be 0 or 1
|
||||||
|
|||||||
@@ -198,7 +198,8 @@ causal_conv1d_update(const at::Tensor &x,
|
|||||||
const at::Tensor &conv_state,
|
const at::Tensor &conv_state,
|
||||||
const at::Tensor &weight,
|
const at::Tensor &weight,
|
||||||
const c10::optional<at::Tensor> &bias_,
|
const c10::optional<at::Tensor> &bias_,
|
||||||
bool silu_activation) {
|
bool silu_activation,
|
||||||
|
const c10::optional<at::Tensor> &conv_state_indices_) {
|
||||||
auto input_type = x.scalar_type();
|
auto input_type = x.scalar_type();
|
||||||
auto weight_type = weight.scalar_type();
|
auto weight_type = weight.scalar_type();
|
||||||
TORCH_CHECK(input_type == at::ScalarType::Float || input_type == at::ScalarType::Half || input_type == at::ScalarType::BFloat16);
|
TORCH_CHECK(input_type == at::ScalarType::Float || input_type == at::ScalarType::Half || input_type == at::ScalarType::BFloat16);
|
||||||
@@ -216,7 +217,6 @@ causal_conv1d_update(const at::Tensor &x,
|
|||||||
const int width = weight.size(-1);
|
const int width = weight.size(-1);
|
||||||
|
|
||||||
CHECK_SHAPE(x, batch_size, dim);
|
CHECK_SHAPE(x, batch_size, dim);
|
||||||
CHECK_SHAPE(conv_state, batch_size, dim, width);
|
|
||||||
CHECK_SHAPE(weight, dim, width);
|
CHECK_SHAPE(weight, dim, width);
|
||||||
|
|
||||||
TORCH_CHECK(width >= 2 && width <= 4, "causal_conv1d only supports width between 2 and 4");
|
TORCH_CHECK(width >= 2 && width <= 4, "causal_conv1d only supports width between 2 and 4");
|
||||||
@@ -241,6 +241,22 @@ causal_conv1d_update(const at::Tensor &x,
|
|||||||
params.conv_state_c_stride = conv_state.stride(1);
|
params.conv_state_c_stride = conv_state.stride(1);
|
||||||
params.conv_state_l_stride = conv_state.stride(2);
|
params.conv_state_l_stride = conv_state.stride(2);
|
||||||
|
|
||||||
|
if (conv_state_indices_.has_value()) {
|
||||||
|
auto conv_state_indices = conv_state_indices_.value();
|
||||||
|
TORCH_CHECK(conv_state_indices.scalar_type() == torch::kInt32)
|
||||||
|
TORCH_CHECK(conv_state_indices.is_cuda());
|
||||||
|
TORCH_CHECK(conv_state_indices.stride(0) == 1)
|
||||||
|
CHECK_SHAPE(conv_state_indices, batch_size);
|
||||||
|
|
||||||
|
int conv_state_entries = conv_state.size(0);
|
||||||
|
CHECK_SHAPE(conv_state, conv_state_entries, dim, width);
|
||||||
|
|
||||||
|
params.conv_state_indices_ptr = conv_state_indices.data_ptr<int32_t>();
|
||||||
|
} else {
|
||||||
|
CHECK_SHAPE(conv_state, batch_size, dim, width);
|
||||||
|
params.conv_state_indices_ptr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise the kernel will be launched from cuda:0 device
|
// Otherwise the kernel will be launched from cuda:0 device
|
||||||
// Cast to char to avoid compiler warning about narrowing
|
// Cast to char to avoid compiler warning about narrowing
|
||||||
at::cuda::CUDAGuard device_guard{(char)x.get_device()};
|
at::cuda::CUDAGuard device_guard{(char)x.get_device()};
|
||||||
@@ -646,8 +662,16 @@ void causal_conv1d_update_kernel(ConvParamsBase params) {
|
|||||||
const int channel_id = blockIdx.y * kNThreads + tidx;
|
const int channel_id = blockIdx.y * kNThreads + tidx;
|
||||||
input_t *x = reinterpret_cast<input_t *>(params.x_ptr) + batch_id * params.x_batch_stride
|
input_t *x = reinterpret_cast<input_t *>(params.x_ptr) + batch_id * params.x_batch_stride
|
||||||
+ channel_id * params.x_c_stride;
|
+ channel_id * params.x_c_stride;
|
||||||
input_t *conv_state = reinterpret_cast<input_t *>(params.conv_state_ptr) + batch_id * params.conv_state_batch_stride
|
|
||||||
|
// If params.conv_state_batch_indices is set, then the conv state is gathered from the conv state tensor
|
||||||
|
// along the batch axis. Otherwise, the conv state coordinate is the same as the batch id.
|
||||||
|
const int conv_state_batch_coord = params.conv_state_indices_ptr == nullptr
|
||||||
|
? batch_id
|
||||||
|
: params.conv_state_indices_ptr[batch_id];
|
||||||
|
input_t *conv_state = reinterpret_cast<input_t *>(params.conv_state_ptr)
|
||||||
|
+ conv_state_batch_coord * params.conv_state_batch_stride
|
||||||
+ channel_id * params.conv_state_c_stride;
|
+ channel_id * params.conv_state_c_stride;
|
||||||
|
|
||||||
weight_t *weight = reinterpret_cast<weight_t *>(params.weight_ptr) + channel_id * params.weight_c_stride;
|
weight_t *weight = reinterpret_cast<weight_t *>(params.weight_ptr) + channel_id * params.weight_c_stride;
|
||||||
input_t *out = reinterpret_cast<input_t *>(params.out_ptr) + batch_id * params.out_batch_stride
|
input_t *out = reinterpret_cast<input_t *>(params.out_ptr) + batch_id * params.out_batch_stride
|
||||||
+ channel_id * params.out_c_stride;
|
+ channel_id * params.out_c_stride;
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ struct ConvParamsBase {
|
|||||||
|
|
||||||
void *__restrict__ conv_state_ptr;
|
void *__restrict__ conv_state_ptr;
|
||||||
|
|
||||||
|
// For the continuous batching case. Makes it so that the mamba state for
|
||||||
|
// the current batch doesn't need to be a contiguous tensor.
|
||||||
|
int32_t *__restrict__ conv_state_indices_ptr;
|
||||||
|
|
||||||
void *__restrict__ seq_idx_ptr;
|
void *__restrict__ seq_idx_ptr;
|
||||||
|
|
||||||
// No __restrict__ since initial_states could be the same as final_states.
|
// No __restrict__ since initial_states could be the same as final_states.
|
||||||
|
|||||||
@@ -586,7 +586,7 @@ selective_scan_fwd(const torch::Tensor &u, const torch::Tensor &delta,
|
|||||||
DISPATCH_WTYPE_ITYPE_FLOAT_AND_HALF_AND_BF16(u.scalar_type(), "selective_scan_fwd", [&] {
|
DISPATCH_WTYPE_ITYPE_FLOAT_AND_HALF_AND_BF16(u.scalar_type(), "selective_scan_fwd", [&] {
|
||||||
selective_scan_fwd_cuda<input_t, weight_t>(params, stream);
|
selective_scan_fwd_cuda<input_t, weight_t>(params, stream);
|
||||||
});
|
});
|
||||||
std::vector<at::Tensor> result = {out, x.value()};
|
std::vector<at::Tensor> result = {out};
|
||||||
if (has_z) { result.push_back(out_z); }
|
if (has_z) { result.push_back(out_z); }
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
1425
csrc/moe/marlin_kernels/marlin_moe_kernel.h
Normal file
1425
csrc/moe/marlin_kernels/marlin_moe_kernel.h
Normal file
File diff suppressed because it is too large
Load Diff
29
csrc/moe/marlin_kernels/marlin_moe_kernel_ku4b8.cu
Normal file
29
csrc/moe/marlin_kernels/marlin_moe_kernel_ku4b8.cu
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "marlin_moe_kernel_ku4b8.h"
|
||||||
|
|
||||||
|
namespace marlin_moe {
|
||||||
|
|
||||||
|
// We return bool so we can create these different kernel calls as a sequence
|
||||||
|
// of if-elseif's.
|
||||||
|
bool call_marlin_moe_kernel_ku4b8(
|
||||||
|
vllm::ScalarType const& q_type, int thread_n_blocks, int thread_k_blocks,
|
||||||
|
bool has_act_order, int group_blocks, int num_threads, int blocks,
|
||||||
|
int max_shared_mem, cudaStream_t stream, const int4* A_ptr,
|
||||||
|
const int4* B_ptr, int4* C_ptr, const int* sorted_ids_ptr,
|
||||||
|
const float* topk_weights_ptr, const int4* s_ptr, const int* g_idx_ptr,
|
||||||
|
int* expert_offsets_ptr, int num_groups, int expert_idx, int num_experts,
|
||||||
|
int topk, int prob_m, int prob_n, int prob_k, int tot_m, int* locks,
|
||||||
|
bool replicate_input, bool apply_weights, int m_block, int max_par,
|
||||||
|
int cfg_max_m_blocks) {
|
||||||
|
if (false) {
|
||||||
|
}
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU4B8, 16, 4, 256)
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU4B8, 8, 8, 256)
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU4B8, 8, 4, 128)
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU4B8, 4, 8, 128)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace marlin_moe
|
||||||
20
csrc/moe/marlin_kernels/marlin_moe_kernel_ku4b8.h
Normal file
20
csrc/moe/marlin_kernels/marlin_moe_kernel_ku4b8.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "marlin_moe_kernel.h"
|
||||||
|
|
||||||
|
namespace marlin_moe {
|
||||||
|
|
||||||
|
// We return bool so we can create these different kernel calls as a sequence
|
||||||
|
// of if-elseif's.
|
||||||
|
bool call_marlin_moe_kernel_ku4b8(
|
||||||
|
vllm::ScalarType const& q_type, int thread_n_blocks, int thread_k_blocks,
|
||||||
|
bool has_act_order, int group_blocks, int num_threads, int blocks,
|
||||||
|
int max_shared_mem, cudaStream_t stream, const int4* A_ptr,
|
||||||
|
const int4* B_ptr, int4* C_ptr, const int* sorted_ids_ptr,
|
||||||
|
const float* topk_weights_ptr, const int4* s_ptr, const int* g_idx_ptr,
|
||||||
|
int* expert_offsets_ptr, int num_groups, int expert_idx, int num_experts,
|
||||||
|
int topk, int prob_m, int prob_n, int prob_k, int tot_m, int* locks,
|
||||||
|
bool replicate_input, bool apply_weights, int m_block, int max_par,
|
||||||
|
int cfg_max_m_blocks);
|
||||||
|
|
||||||
|
} // namespace marlin_moe
|
||||||
29
csrc/moe/marlin_kernels/marlin_moe_kernel_ku8b128.cu
Normal file
29
csrc/moe/marlin_kernels/marlin_moe_kernel_ku8b128.cu
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "marlin_moe_kernel_ku8b128.h"
|
||||||
|
|
||||||
|
namespace marlin_moe {
|
||||||
|
|
||||||
|
// We return bool so we can create these different kernel calls as a sequence
|
||||||
|
// of if-elseif's.
|
||||||
|
bool call_marlin_moe_kernel_ku8b128(
|
||||||
|
vllm::ScalarType const& q_type, int thread_n_blocks, int thread_k_blocks,
|
||||||
|
bool has_act_order, int group_blocks, int num_threads, int blocks,
|
||||||
|
int max_shared_mem, cudaStream_t stream, const int4* A_ptr,
|
||||||
|
const int4* B_ptr, int4* C_ptr, const int* sorted_ids_ptr,
|
||||||
|
const float* topk_weights_ptr, const int4* s_ptr, const int* g_idx_ptr,
|
||||||
|
int* expert_offsets_ptr, int num_groups, int expert_idx, int num_experts,
|
||||||
|
int topk, int prob_m, int prob_n, int prob_k, int tot_m, int* locks,
|
||||||
|
bool replicate_input, bool apply_weights, int m_block, int max_par,
|
||||||
|
int cfg_max_m_blocks) {
|
||||||
|
if (false) {
|
||||||
|
}
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU8B128, 16, 4, 256)
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU8B128, 8, 8, 256)
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU8B128, 8, 4, 128)
|
||||||
|
GPTQ_CALL_IF_MOE(vllm::kU8B128, 4, 8, 128)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace marlin_moe
|
||||||
18
csrc/moe/marlin_kernels/marlin_moe_kernel_ku8b128.h
Normal file
18
csrc/moe/marlin_kernels/marlin_moe_kernel_ku8b128.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "marlin_moe_kernel.h"
|
||||||
|
|
||||||
|
namespace marlin_moe {
|
||||||
|
|
||||||
|
bool call_marlin_moe_kernel_ku8b128(
|
||||||
|
vllm::ScalarType const& q_type, int thread_n_blocks, int thread_k_blocks,
|
||||||
|
bool has_act_order, int group_blocks, int num_threads, int blocks,
|
||||||
|
int max_shared_mem, cudaStream_t stream, const int4* A_ptr,
|
||||||
|
const int4* B_ptr, int4* C_ptr, const int* sorted_ids_ptr,
|
||||||
|
const float* topk_weights_ptr, const int4* s_ptr, const int* g_idx_ptr,
|
||||||
|
int* expert_offsets_ptr, int num_groups, int expert_idx, int num_experts,
|
||||||
|
int topk, int prob_m, int prob_n, int prob_k, int tot_m, int* locks,
|
||||||
|
bool replicate_input, bool apply_weights, int m_block, int max_par,
|
||||||
|
int cfg_max_m_blocks);
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
#include <torch/all.h>
|
#include <torch/all.h>
|
||||||
|
|
||||||
|
#include "core/scalar_type.hpp"
|
||||||
|
|
||||||
torch::Tensor marlin_gemm_moe(
|
torch::Tensor marlin_gemm_moe(
|
||||||
const torch::Tensor& a, const torch::Tensor& b_q_weights,
|
const torch::Tensor& a, const torch::Tensor& b_q_weights,
|
||||||
const torch::Tensor& sorted_ids, const torch::Tensor& topk_weights,
|
const torch::Tensor& sorted_ids, const torch::Tensor& topk_weights,
|
||||||
const torch::Tensor& topk_ids, const torch::Tensor& b_scales,
|
const torch::Tensor& topk_ids, const torch::Tensor& b_scales,
|
||||||
const torch::Tensor& g_idx, const torch::Tensor& perm,
|
const torch::Tensor& g_idx, const torch::Tensor& perm,
|
||||||
torch::Tensor& workspace, int64_t size_m, int64_t size_n, int64_t size_k,
|
torch::Tensor& workspace, vllm::ScalarTypeTorchPtr const& b_q_type,
|
||||||
bool is_k_full, int64_t num_experts, int64_t topk, int64_t moe_block_size,
|
int64_t size_m, int64_t size_n, int64_t size_k, bool is_k_full,
|
||||||
|
int64_t num_experts, int64_t topk, int64_t moe_block_size,
|
||||||
bool replicate_input, bool apply_weights);
|
bool replicate_input, bool apply_weights);
|
||||||
|
|||||||
@@ -13,9 +13,11 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, m) {
|
|||||||
m.def(
|
m.def(
|
||||||
"marlin_gemm_moe(Tensor! a, Tensor! b_q_weights, Tensor! sorted_ids, "
|
"marlin_gemm_moe(Tensor! a, Tensor! b_q_weights, Tensor! sorted_ids, "
|
||||||
"Tensor! topk_weights, Tensor! topk_ids, Tensor! b_scales, Tensor! "
|
"Tensor! topk_weights, Tensor! topk_ids, Tensor! b_scales, Tensor! "
|
||||||
"g_idx, Tensor! perm, Tensor! workspace, int size_m, int size_n, int "
|
"g_idx, Tensor! perm, Tensor! workspace, "
|
||||||
"size_k, bool is_k_full, int num_experts, int topk, int moe_block_size, "
|
"__torch__.torch.classes._core_C.ScalarType b_q_type, int size_m, "
|
||||||
"bool replicate_input, bool apply_weights) -> Tensor");
|
"int size_n, int size_k, bool is_k_full, int num_experts, int topk, "
|
||||||
|
"int moe_block_size, bool replicate_input, bool apply_weights)"
|
||||||
|
" -> Tensor");
|
||||||
m.impl("marlin_gemm_moe", torch::kCUDA, &marlin_gemm_moe);
|
m.impl("marlin_gemm_moe", torch::kCUDA, &marlin_gemm_moe);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
38
csrc/ops.h
38
csrc/ops.h
@@ -54,10 +54,21 @@ void gelu_fast(torch::Tensor& out, torch::Tensor& input);
|
|||||||
|
|
||||||
void gelu_quick(torch::Tensor& out, torch::Tensor& input);
|
void gelu_quick(torch::Tensor& out, torch::Tensor& input);
|
||||||
|
|
||||||
void advance_step(int64_t num_seqs, int64_t num_queries, int64_t block_size,
|
void advance_step_flashattn(int64_t num_seqs, int64_t num_queries,
|
||||||
torch::Tensor& input_tokens, torch::Tensor& sampled_token_ids,
|
int64_t block_size, torch::Tensor& input_tokens,
|
||||||
torch::Tensor& input_positions, torch::Tensor& seq_lens,
|
torch::Tensor& sampled_token_ids,
|
||||||
torch::Tensor& slot_mapping, torch::Tensor& block_tables);
|
torch::Tensor& input_positions,
|
||||||
|
torch::Tensor& seq_lens,
|
||||||
|
torch::Tensor& slot_mapping,
|
||||||
|
torch::Tensor& block_tables);
|
||||||
|
|
||||||
|
void advance_step_flashinfer(
|
||||||
|
int64_t num_seqs, int64_t num_queries, int64_t block_size,
|
||||||
|
torch::Tensor& input_tokens, torch::Tensor& sampled_token_ids,
|
||||||
|
torch::Tensor& input_positions, torch::Tensor& seq_lens,
|
||||||
|
torch::Tensor& slot_mapping, torch::Tensor& block_tables,
|
||||||
|
torch::Tensor& paged_kv_indices, torch::Tensor& paged_kv_indptr,
|
||||||
|
torch::Tensor& paged_kv_last_page_len, torch::Tensor& block_table_bounds);
|
||||||
|
|
||||||
#ifndef USE_ROCM
|
#ifndef USE_ROCM
|
||||||
torch::Tensor aqlm_gemm(const torch::Tensor& input, const torch::Tensor& codes,
|
torch::Tensor aqlm_gemm(const torch::Tensor& input, const torch::Tensor& codes,
|
||||||
@@ -102,6 +113,8 @@ torch::Tensor prepack_B(torch::Tensor const& B,
|
|||||||
|
|
||||||
}; // namespace machete
|
}; // namespace machete
|
||||||
|
|
||||||
|
torch::Tensor permute_cols(torch::Tensor const& A, torch::Tensor const& perm);
|
||||||
|
|
||||||
torch::Tensor gptq_marlin_24_gemm(torch::Tensor& a, torch::Tensor& b_q_weight,
|
torch::Tensor gptq_marlin_24_gemm(torch::Tensor& a, torch::Tensor& b_q_weight,
|
||||||
torch::Tensor& b_meta,
|
torch::Tensor& b_meta,
|
||||||
torch::Tensor& b_scales,
|
torch::Tensor& b_scales,
|
||||||
@@ -173,10 +186,12 @@ torch::Tensor marlin_qqq_gemm(torch::Tensor const& a,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void static_scaled_int8_quant(torch::Tensor& out, torch::Tensor const& input,
|
void static_scaled_int8_quant(torch::Tensor& out, torch::Tensor const& input,
|
||||||
torch::Tensor const& scale);
|
torch::Tensor const& scale,
|
||||||
|
c10::optional<torch::Tensor> const& azp);
|
||||||
|
|
||||||
void dynamic_scaled_int8_quant(torch::Tensor& out, torch::Tensor const& input,
|
void dynamic_scaled_int8_quant(torch::Tensor& out, torch::Tensor const& input,
|
||||||
torch::Tensor& scales);
|
torch::Tensor& scales,
|
||||||
|
c10::optional<torch::Tensor> const& azp);
|
||||||
|
|
||||||
torch::Tensor gptq_gemm(torch::Tensor a, torch::Tensor b_q_weight,
|
torch::Tensor gptq_gemm(torch::Tensor a, torch::Tensor b_q_weight,
|
||||||
torch::Tensor b_gptq_qzeros,
|
torch::Tensor b_gptq_qzeros,
|
||||||
@@ -209,11 +224,10 @@ std::vector<torch::Tensor> selective_scan_fwd(
|
|||||||
const c10::optional<torch::Tensor>& index_,
|
const c10::optional<torch::Tensor>& index_,
|
||||||
const c10::optional<torch::Tensor>& x);
|
const c10::optional<torch::Tensor>& x);
|
||||||
|
|
||||||
at::Tensor causal_conv1d_update(const at::Tensor& x,
|
at::Tensor causal_conv1d_update(
|
||||||
const at::Tensor& conv_state,
|
const at::Tensor& x, const at::Tensor& conv_state, const at::Tensor& weight,
|
||||||
const at::Tensor& weight,
|
const c10::optional<at::Tensor>& bias, bool silu_activation,
|
||||||
const c10::optional<at::Tensor>& bias_,
|
const c10::optional<at::Tensor>& conv_state_indices);
|
||||||
bool silu_activation);
|
|
||||||
|
|
||||||
at::Tensor causal_conv1d_fwd(const at::Tensor& x, const at::Tensor& weight,
|
at::Tensor causal_conv1d_fwd(const at::Tensor& x, const at::Tensor& weight,
|
||||||
const c10::optional<at::Tensor>& bias_,
|
const c10::optional<at::Tensor>& bias_,
|
||||||
@@ -228,8 +242,6 @@ fptr_t init_custom_ar(torch::Tensor& meta, torch::Tensor& rank_data,
|
|||||||
const std::vector<std::string>& handles,
|
const std::vector<std::string>& handles,
|
||||||
const std::vector<int64_t>& offsets, int64_t rank,
|
const std::vector<int64_t>& offsets, int64_t rank,
|
||||||
bool full_nvlink);
|
bool full_nvlink);
|
||||||
bool should_custom_ar(torch::Tensor& inp, int64_t max_size, int64_t world_size,
|
|
||||||
bool full_nvlink);
|
|
||||||
void all_reduce_reg(fptr_t _fa, torch::Tensor& inp, torch::Tensor& out);
|
void all_reduce_reg(fptr_t _fa, torch::Tensor& inp, torch::Tensor& out);
|
||||||
void all_reduce_unreg(fptr_t _fa, torch::Tensor& inp, torch::Tensor& reg_buffer,
|
void all_reduce_unreg(fptr_t _fa, torch::Tensor& inp, torch::Tensor& reg_buffer,
|
||||||
torch::Tensor& out);
|
torch::Tensor& out);
|
||||||
|
|||||||
88
csrc/permute_cols.cu
Normal file
88
csrc/permute_cols.cu
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#include <torch/all.h>
|
||||||
|
|
||||||
|
#include <ATen/cuda/CUDAContext.h>
|
||||||
|
#include <c10/cuda/CUDAGuard.h>
|
||||||
|
|
||||||
|
#include <cuda_fp16.h>
|
||||||
|
|
||||||
|
static constexpr int default_threads = 256;
|
||||||
|
static constexpr int div_ceil(int a, int b) { return (a + b - 1) / b; }
|
||||||
|
|
||||||
|
// For a given "a" of size [M,K] performs a permutation of the K columns based
|
||||||
|
// on the given "perm" indices.
|
||||||
|
// Currently only supports 16bit types (since we permute half types)
|
||||||
|
__global__ void permute_cols_kernel(int4 const* __restrict__ a_int4_ptr,
|
||||||
|
int const* __restrict__ perm_int_ptr,
|
||||||
|
int4* __restrict__ out_int4_ptr, int size_m,
|
||||||
|
int size_k, int block_rows) {
|
||||||
|
int start_row = block_rows * blockIdx.x;
|
||||||
|
int finish_row = start_row + block_rows;
|
||||||
|
if (finish_row > size_m) {
|
||||||
|
finish_row = size_m;
|
||||||
|
}
|
||||||
|
int cur_block_rows = std::max(finish_row - start_row, 0);
|
||||||
|
|
||||||
|
int row_stride = size_k * sizeof(half) / 16;
|
||||||
|
|
||||||
|
auto permute_row = [&](int row) {
|
||||||
|
int iters = size_k / default_threads;
|
||||||
|
int rest = size_k % default_threads;
|
||||||
|
|
||||||
|
int offset = row * row_stride;
|
||||||
|
|
||||||
|
half const* a_row_half = reinterpret_cast<half const*>(a_int4_ptr + offset);
|
||||||
|
half* out_half = reinterpret_cast<half*>(out_int4_ptr + offset);
|
||||||
|
|
||||||
|
int base_k = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < iters; i++) {
|
||||||
|
int cur_k = base_k + threadIdx.x;
|
||||||
|
int src_pos = perm_int_ptr[cur_k];
|
||||||
|
|
||||||
|
out_half[cur_k] = a_row_half[src_pos];
|
||||||
|
|
||||||
|
base_k += default_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rest) {
|
||||||
|
if (threadIdx.x < rest) {
|
||||||
|
int cur_k = base_k + threadIdx.x;
|
||||||
|
int src_pos = perm_int_ptr[cur_k];
|
||||||
|
|
||||||
|
out_half[cur_k] = a_row_half[src_pos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < cur_block_rows; i++) {
|
||||||
|
int cur_row = start_row + i;
|
||||||
|
if (cur_row < size_m) {
|
||||||
|
permute_row(cur_row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// More efficient version of A[..., perm]
|
||||||
|
// taken from gptq_marlin.cu
|
||||||
|
torch::Tensor permute_cols(torch::Tensor const& A, torch::Tensor const& perm) {
|
||||||
|
const at::cuda::OptionalCUDAGuard device_guard(device_of(A));
|
||||||
|
auto dev = A.get_device();
|
||||||
|
auto stream = at::cuda::getCurrentCUDAStream(dev);
|
||||||
|
|
||||||
|
TORCH_CHECK(A.scalar_type() == at::kHalf || A.scalar_type() == at::kBFloat16,
|
||||||
|
"Currently only 16bit types are supported");
|
||||||
|
TORCH_CHECK(A.is_contiguous(), "A must be contiguous");
|
||||||
|
TORCH_CHECK(A.size(-1) % 8 == 0,
|
||||||
|
"A columns must be a multiple of 8 (128bits)");
|
||||||
|
auto A_2d = A.view({-1, A.size(-1)});
|
||||||
|
|
||||||
|
torch::Tensor D = torch::empty_like(A);
|
||||||
|
int sms;
|
||||||
|
cudaDeviceGetAttribute(&sms, cudaDevAttrMultiProcessorCount, dev);
|
||||||
|
int block_rows = div_ceil(A_2d.size(0), sms);
|
||||||
|
permute_cols_kernel<<<sms, default_threads, 0, stream>>>(
|
||||||
|
reinterpret_cast<int4 const*>(A_2d.const_data_ptr()),
|
||||||
|
perm.const_data_ptr<int>(), reinterpret_cast<int4*>(D.mutable_data_ptr()),
|
||||||
|
A_2d.size(0), A_2d.size(1), block_rows);
|
||||||
|
return D;
|
||||||
|
}
|
||||||
@@ -12,13 +12,11 @@ namespace prepare_inputs {
|
|||||||
|
|
||||||
//
|
//
|
||||||
template <int const num_threads>
|
template <int const num_threads>
|
||||||
__global__ void advance_step_kernel(int num_seqs, int num_queries,
|
__global__ void advance_step_flashattn_kernel(
|
||||||
int block_size, long* input_tokens_ptr,
|
int num_seqs, int num_queries, int block_size, long* input_tokens_ptr,
|
||||||
long const* sampled_token_ids_ptr,
|
long const* sampled_token_ids_ptr, long* input_positions_ptr,
|
||||||
long* input_positions_ptr,
|
int* seq_lens_ptr, long* slot_mapping_ptr, int const* block_tables_ptr,
|
||||||
int* seq_lens_ptr, long* slot_mapping_ptr,
|
int64_t const block_tables_stride) {
|
||||||
int const* block_tables_ptr,
|
|
||||||
int64_t const block_tables_stride) {
|
|
||||||
int num_query_blocks = div_ceil(num_queries, num_threads);
|
int num_query_blocks = div_ceil(num_queries, num_threads);
|
||||||
|
|
||||||
if (blockIdx.x >= num_query_blocks) {
|
if (blockIdx.x >= num_query_blocks) {
|
||||||
@@ -79,16 +77,91 @@ inline void verify_tensor(std::string const& name, torch::Tensor& t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void advance_step(int num_seqs, int num_queries, int block_size,
|
__global__ void advance_step_flashinfer_kernel(
|
||||||
torch::Tensor& input_tokens, // type: long
|
int num_threads, int num_seqs, int num_queries, int block_size,
|
||||||
torch::Tensor& sampled_token_ids, // type: long
|
long* input_tokens_ptr, long const* sampled_token_ids_ptr,
|
||||||
torch::Tensor& input_positions, // type: long
|
long* input_positions_ptr, int* seq_lens_ptr, long* slot_mapping_ptr,
|
||||||
torch::Tensor& seq_lens, // type: int
|
int const* block_tables_ptr, int64_t const block_tables_stride,
|
||||||
torch::Tensor& slot_mapping, // type: long
|
int* paged_kv_last_page_len_ptr, int* block_table_bound_ptr) {
|
||||||
torch::Tensor& block_tables) { // type: int
|
int num_query_blocks = div_ceil(num_queries, num_threads);
|
||||||
|
|
||||||
|
if (blockIdx.x < num_query_blocks) {
|
||||||
|
int cur_query_id = blockIdx.x * num_threads + threadIdx.x;
|
||||||
|
|
||||||
|
if (cur_query_id < num_queries) {
|
||||||
|
// Update input_tokens
|
||||||
|
input_tokens_ptr[cur_query_id] = sampled_token_ids_ptr[cur_query_id];
|
||||||
|
|
||||||
|
int seq_len = seq_lens_ptr[cur_query_id];
|
||||||
|
int next_seq_len = seq_len + 1;
|
||||||
|
int next_input_pos = next_seq_len - 1;
|
||||||
|
|
||||||
|
// Update seq_lens
|
||||||
|
seq_lens_ptr[cur_query_id] = next_seq_len;
|
||||||
|
// Update input_positions
|
||||||
|
input_positions_ptr[cur_query_id] = next_input_pos;
|
||||||
|
|
||||||
|
int const* seq_block_tables_ptr =
|
||||||
|
block_tables_ptr + block_tables_stride * cur_query_id;
|
||||||
|
|
||||||
|
int block_index = next_input_pos / block_size;
|
||||||
|
int block_offset = next_input_pos % block_size;
|
||||||
|
|
||||||
|
// Update paged_kv_last_page_len
|
||||||
|
paged_kv_last_page_len_ptr[cur_query_id] = block_offset + 1;
|
||||||
|
|
||||||
|
int slot_num =
|
||||||
|
seq_block_tables_ptr[block_index] * block_size + block_offset;
|
||||||
|
// Update slot_mapping
|
||||||
|
slot_mapping_ptr[cur_query_id] = slot_num;
|
||||||
|
block_table_bound_ptr[cur_query_id] = div_ceil(next_seq_len, block_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__global__ void advance_step_flashinfer_indptr_kernel(
|
||||||
|
int num_threads, int num_seqs, int num_queries, int* paged_kv_indptr_ptr,
|
||||||
|
int* block_table_bound_ptr) {
|
||||||
|
int idx = blockIdx.x * num_threads + threadIdx.x;
|
||||||
|
|
||||||
|
// Update paged_kv_indptr
|
||||||
|
if (idx < num_queries) {
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i <= idx; ++i) {
|
||||||
|
sum += block_table_bound_ptr[i];
|
||||||
|
}
|
||||||
|
paged_kv_indptr_ptr[idx + 1] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__global__ void advance_step_flashinfer_indices_kernel(
|
||||||
|
int num_threads, int num_seqs, int num_queries, int const* block_tables_ptr,
|
||||||
|
int64_t const block_tables_stride, int* paged_kv_indices_ptr,
|
||||||
|
int* paged_kv_indptr_ptr, int* block_table_bound_ptr) {
|
||||||
|
int idx = blockIdx.x * num_threads + threadIdx.x;
|
||||||
|
int row = idx / block_tables_stride;
|
||||||
|
int col = idx % block_tables_stride;
|
||||||
|
|
||||||
|
if (row < num_queries && col < block_table_bound_ptr[row]) {
|
||||||
|
paged_kv_indices_ptr[paged_kv_indptr_ptr[row] + col] =
|
||||||
|
block_tables_ptr[row * block_tables_stride + col];
|
||||||
|
}
|
||||||
|
// if cudagraph, fill padded seqs with the last valid seq's indptr
|
||||||
|
if (num_queries < row && row <= num_seqs) {
|
||||||
|
paged_kv_indptr_ptr[row] = paged_kv_indptr_ptr[num_queries];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void advance_step_flashattn(int num_seqs, int num_queries, int block_size,
|
||||||
|
torch::Tensor& input_tokens, // type: long
|
||||||
|
torch::Tensor& sampled_token_ids, // type: long
|
||||||
|
torch::Tensor& input_positions, // type: long
|
||||||
|
torch::Tensor& seq_lens, // type: int
|
||||||
|
torch::Tensor& slot_mapping, // type: long
|
||||||
|
torch::Tensor& block_tables) { // type: int
|
||||||
|
|
||||||
if (logging) {
|
if (logging) {
|
||||||
printf("advance_step:\n");
|
printf("advance_step_flashattn:\n");
|
||||||
printf(" num_seqs = %d\n", num_seqs);
|
printf(" num_seqs = %d\n", num_seqs);
|
||||||
printf(" num_queries = %d\n", num_queries);
|
printf(" num_queries = %d\n", num_queries);
|
||||||
printf(" block_size = %d\n", block_size);
|
printf(" block_size = %d\n", block_size);
|
||||||
@@ -108,24 +181,126 @@ void advance_step(int num_seqs, int num_queries, int block_size,
|
|||||||
int blocks;
|
int blocks;
|
||||||
cudaDeviceGetAttribute(&blocks, cudaDevAttrMultiProcessorCount, dev);
|
cudaDeviceGetAttribute(&blocks, cudaDevAttrMultiProcessorCount, dev);
|
||||||
|
|
||||||
advance_step_kernel<max_threads><<<blocks, max_threads, 0, stream>>>(
|
advance_step_flashattn_kernel<max_threads>
|
||||||
num_seqs, num_queries, block_size,
|
<<<blocks, max_threads, 0, stream>>>(
|
||||||
|
num_seqs, num_queries, block_size,
|
||||||
|
reinterpret_cast<long*>(input_tokens.data_ptr()),
|
||||||
|
reinterpret_cast<long const*>(sampled_token_ids.data_ptr()),
|
||||||
|
reinterpret_cast<long*>(input_positions.data_ptr()),
|
||||||
|
reinterpret_cast<int*>(seq_lens.data_ptr()),
|
||||||
|
reinterpret_cast<long*>(slot_mapping.data_ptr()),
|
||||||
|
reinterpret_cast<int const*>(block_tables.data_ptr()),
|
||||||
|
block_tables.stride(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void advance_step_flashinfer(
|
||||||
|
int num_seqs, int num_queries, int block_size,
|
||||||
|
torch::Tensor& input_tokens, // type: long
|
||||||
|
torch::Tensor& sampled_token_ids, // type: long
|
||||||
|
torch::Tensor& input_positions, // type: long
|
||||||
|
torch::Tensor& seq_lens, // type: int
|
||||||
|
torch::Tensor& slot_mapping, // type: long
|
||||||
|
torch::Tensor& block_tables, // type: int
|
||||||
|
torch::Tensor& paged_kv_indices, // type: int
|
||||||
|
torch::Tensor& paged_kv_indptr, // type: int
|
||||||
|
torch::Tensor& paged_kv_last_page_len, // type: int
|
||||||
|
torch::Tensor& block_table_bound) { // type: int
|
||||||
|
|
||||||
|
if (logging) {
|
||||||
|
printf("advance_step_flashinfer:\n");
|
||||||
|
printf(" num_seqs = %d\n", num_seqs);
|
||||||
|
printf(" num_queries = %d\n", num_queries);
|
||||||
|
printf(" block_size = %d\n", block_size);
|
||||||
|
printf(" block_tables.stride(0) = %d\n", block_tables.stride(0));
|
||||||
|
}
|
||||||
|
// Verify all tensors
|
||||||
|
verify_tensor("input_tokens", input_tokens, num_seqs, -1, at::kLong);
|
||||||
|
// verify_tensor("sampled_token_ids", sampled_token_ids, num_queries, 1,
|
||||||
|
// at::kLong);
|
||||||
|
verify_tensor("input_positions", input_positions, num_seqs, -1, at::kLong);
|
||||||
|
verify_tensor("seq_lens", seq_lens, num_seqs, -1, at::kInt);
|
||||||
|
verify_tensor("slot_mapping", slot_mapping, num_seqs, -1, at::kLong);
|
||||||
|
verify_tensor("block_tables", block_tables, num_seqs, -1, at::kInt);
|
||||||
|
|
||||||
|
verify_tensor("paged_kv_indices", paged_kv_indices, -1, -1, at::kInt);
|
||||||
|
verify_tensor("paged_kv_indptr", paged_kv_indptr, num_seqs + 1, -1, at::kInt);
|
||||||
|
verify_tensor("paged_kv_last_page_len", paged_kv_last_page_len, num_seqs, -1,
|
||||||
|
at::kInt);
|
||||||
|
|
||||||
|
verify_tensor("block_table_bound", block_table_bound, num_seqs, -1, at::kInt);
|
||||||
|
|
||||||
|
int dev = sampled_token_ids.get_device();
|
||||||
|
cudaStream_t stream = at::cuda::getCurrentCUDAStream(dev);
|
||||||
|
|
||||||
|
int blocks;
|
||||||
|
int threads;
|
||||||
|
cudaDeviceGetAttribute(&blocks, cudaDevAttrMultiProcessorCount, dev);
|
||||||
|
cudaDeviceGetAttribute(&threads, cudaDevAttrMaxThreadsPerBlock, dev);
|
||||||
|
if (logging) {
|
||||||
|
printf("launching kernel with %d blocks\n", blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(will): support arbitrary block_tables stride
|
||||||
|
if ((blocks * threads) / block_tables.stride(0) < num_queries) {
|
||||||
|
TORCH_CHECK(false,
|
||||||
|
"multi-step: not enough threads to map block_table to"
|
||||||
|
"FlashInfer's paged_kv_indices on GPU. Try reducing the number "
|
||||||
|
"of seqs,",
|
||||||
|
" increasing the block size or take smaller steps.",
|
||||||
|
" num_queries = ", num_queries,
|
||||||
|
" block_tables.stride(0) = ", block_tables.stride(0),
|
||||||
|
" blocks = ", blocks, " max_threads = ", threads);
|
||||||
|
}
|
||||||
|
|
||||||
|
advance_step_flashinfer_kernel<<<blocks, threads, 0, stream>>>(
|
||||||
|
threads, num_seqs, num_queries, block_size,
|
||||||
reinterpret_cast<long*>(input_tokens.data_ptr()),
|
reinterpret_cast<long*>(input_tokens.data_ptr()),
|
||||||
reinterpret_cast<long const*>(sampled_token_ids.data_ptr()),
|
reinterpret_cast<long const*>(sampled_token_ids.data_ptr()),
|
||||||
reinterpret_cast<long*>(input_positions.data_ptr()),
|
reinterpret_cast<long*>(input_positions.data_ptr()),
|
||||||
reinterpret_cast<int*>(seq_lens.data_ptr()),
|
reinterpret_cast<int*>(seq_lens.data_ptr()),
|
||||||
reinterpret_cast<long*>(slot_mapping.data_ptr()),
|
reinterpret_cast<long*>(slot_mapping.data_ptr()),
|
||||||
reinterpret_cast<int const*>(block_tables.data_ptr()),
|
reinterpret_cast<int const*>(block_tables.data_ptr()),
|
||||||
block_tables.stride(0));
|
block_tables.stride(0),
|
||||||
|
reinterpret_cast<int*>(paged_kv_last_page_len.data_ptr()),
|
||||||
|
reinterpret_cast<int*>(block_table_bound.data_ptr()));
|
||||||
|
|
||||||
|
advance_step_flashinfer_indptr_kernel<<<blocks, threads, 0, stream>>>(
|
||||||
|
threads, num_seqs, num_queries,
|
||||||
|
reinterpret_cast<int*>(paged_kv_indptr.data_ptr()),
|
||||||
|
reinterpret_cast<int*>(block_table_bound.data_ptr()));
|
||||||
|
|
||||||
|
advance_step_flashinfer_indices_kernel<<<blocks, threads, 0, stream>>>(
|
||||||
|
threads, num_seqs, num_queries,
|
||||||
|
reinterpret_cast<int const*>(block_tables.data_ptr()),
|
||||||
|
block_tables.stride(0),
|
||||||
|
reinterpret_cast<int*>(paged_kv_indices.data_ptr()),
|
||||||
|
reinterpret_cast<int*>(paged_kv_indptr.data_ptr()),
|
||||||
|
reinterpret_cast<int*>(block_table_bound.data_ptr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace prepare_inputs
|
} // namespace prepare_inputs
|
||||||
|
|
||||||
void advance_step(int64_t num_seqs, int64_t num_queries, int64_t block_size,
|
void advance_step_flashattn(int64_t num_seqs, int64_t num_queries,
|
||||||
torch::Tensor& input_tokens, torch::Tensor& sampled_token_ids,
|
int64_t block_size, torch::Tensor& input_tokens,
|
||||||
torch::Tensor& input_positions, torch::Tensor& seq_lens,
|
torch::Tensor& sampled_token_ids,
|
||||||
torch::Tensor& slot_mapping, torch::Tensor& block_tables) {
|
torch::Tensor& input_positions,
|
||||||
prepare_inputs::advance_step(num_seqs, num_queries, block_size, input_tokens,
|
torch::Tensor& seq_lens,
|
||||||
sampled_token_ids, input_positions, seq_lens,
|
torch::Tensor& slot_mapping,
|
||||||
slot_mapping, block_tables);
|
torch::Tensor& block_tables) {
|
||||||
|
prepare_inputs::advance_step_flashattn(
|
||||||
|
num_seqs, num_queries, block_size, input_tokens, sampled_token_ids,
|
||||||
|
input_positions, seq_lens, slot_mapping, block_tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
void advance_step_flashinfer(
|
||||||
|
int64_t num_seqs, int64_t num_queries, int64_t block_size,
|
||||||
|
torch::Tensor& input_tokens, torch::Tensor& sampled_token_ids,
|
||||||
|
torch::Tensor& input_positions, torch::Tensor& seq_lens,
|
||||||
|
torch::Tensor& slot_mapping, torch::Tensor& block_tables,
|
||||||
|
torch::Tensor& paged_kv_indices, torch::Tensor& paged_kv_indptr,
|
||||||
|
torch::Tensor& paged_kv_last_page_len, torch::Tensor& block_table_bound) {
|
||||||
|
prepare_inputs::advance_step_flashinfer(
|
||||||
|
num_seqs, num_queries, block_size, input_tokens, sampled_token_ids,
|
||||||
|
input_positions, seq_lens, slot_mapping, block_tables, paged_kv_indices,
|
||||||
|
paged_kv_indptr, paged_kv_last_page_len, block_table_bound);
|
||||||
}
|
}
|
||||||
@@ -14,12 +14,17 @@
|
|||||||
|
|
||||||
static inline __device__ int8_t float_to_int8_rn(float x) {
|
static inline __device__ int8_t float_to_int8_rn(float x) {
|
||||||
#ifdef USE_ROCM
|
#ifdef USE_ROCM
|
||||||
static const float i8_min =
|
static constexpr auto i8_min =
|
||||||
static_cast<float>(std::numeric_limits<int8_t>::min());
|
static_cast<float>(std::numeric_limits<int8_t>::min());
|
||||||
static const float i8_max =
|
static constexpr auto i8_max =
|
||||||
static_cast<float>(std::numeric_limits<int8_t>::max());
|
static_cast<float>(std::numeric_limits<int8_t>::max());
|
||||||
// round
|
|
||||||
|
// To match the rounding mode of CUDA, we use nearbyint.
|
||||||
|
// It uses the current rounding mode, which is always FE_TONEAREST on HIP.
|
||||||
|
// If that changes in the future, we may need to set the rounding mode
|
||||||
|
// explicitly, either at runtime or compile time.
|
||||||
float dst = std::nearbyint(x);
|
float dst = std::nearbyint(x);
|
||||||
|
|
||||||
// saturate
|
// saturate
|
||||||
dst = std::clamp(dst, i8_min, i8_max);
|
dst = std::clamp(dst, i8_min, i8_max);
|
||||||
return static_cast<int8_t>(dst);
|
return static_cast<int8_t>(dst);
|
||||||
@@ -31,6 +36,59 @@ static inline __device__ int8_t float_to_int8_rn(float x) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline __device__ int32_t float_to_int32_rn(float x) {
|
||||||
|
#ifdef USE_ROCM
|
||||||
|
// int32_max is not exactly representable as float.
|
||||||
|
// Therefore, we need to be careful and manually return int32_max on overflow.
|
||||||
|
// For symmetry, we also do the same for int32_min, even though it is exactly
|
||||||
|
// representable as float and the conversion should be exact.
|
||||||
|
static constexpr auto i32_min = std::numeric_limits<int32_t>::min();
|
||||||
|
static constexpr auto i32_min_f = static_cast<float>(i32_min);
|
||||||
|
static constexpr auto i32_max = std::numeric_limits<int32_t>::max();
|
||||||
|
static constexpr auto i32_max_f = static_cast<float>(i32_max);
|
||||||
|
|
||||||
|
// To match the rounding mode of CUDA, we use nearbyint.
|
||||||
|
// It uses the current rounding mode, which is always FE_TONEAREST on HIP.
|
||||||
|
// If that changes in the future, we may need to set the rounding mode
|
||||||
|
// explicitly, either at runtime or compile time.
|
||||||
|
float dst = std::nearbyint(x);
|
||||||
|
|
||||||
|
// saturate on the higher end.
|
||||||
|
if (dst >= i32_max_f) {
|
||||||
|
return i32_max;
|
||||||
|
}
|
||||||
|
// saturate on the lower end.
|
||||||
|
if (dst <= i32_min_f) {
|
||||||
|
return i32_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int32_t>(dst);
|
||||||
|
#else
|
||||||
|
// CUDA path
|
||||||
|
uint32_t dst;
|
||||||
|
asm volatile("cvt.rni.sat.s32.f32 %0, %1;" : "=r"(dst) : "f"(x));
|
||||||
|
return reinterpret_cast<const int32_t&>(dst);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __device__ int8_t int32_to_int8(int32_t x) {
|
||||||
|
#ifdef USE_ROCM
|
||||||
|
static constexpr auto i8_min =
|
||||||
|
static_cast<int32_t>(std::numeric_limits<int8_t>::min());
|
||||||
|
static constexpr auto i8_max =
|
||||||
|
static_cast<int32_t>(std::numeric_limits<int8_t>::max());
|
||||||
|
|
||||||
|
// saturate
|
||||||
|
int32_t dst = std::clamp(x, i8_min, i8_max);
|
||||||
|
return static_cast<int8_t>(dst);
|
||||||
|
#else
|
||||||
|
// CUDA path
|
||||||
|
uint32_t dst;
|
||||||
|
asm volatile("cvt.sat.s8.s32 %0, %1;" : "=r"(dst) : "r"(x));
|
||||||
|
return reinterpret_cast<const int8_t&>(dst);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
namespace vllm {
|
namespace vllm {
|
||||||
|
|
||||||
template <typename scalar_t, typename scale_type>
|
template <typename scalar_t, typename scale_type>
|
||||||
@@ -47,6 +105,23 @@ __global__ void static_scaled_int8_quant_kernel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename scalar_t, typename scale_type, typename azp_type>
|
||||||
|
__global__ void static_scaled_int8_azp_quant_kernel(
|
||||||
|
scalar_t const* __restrict__ input, int8_t* __restrict__ out,
|
||||||
|
scale_type const* scale_ptr, azp_type const* azp_ptr,
|
||||||
|
const int hidden_size) {
|
||||||
|
int const tid = threadIdx.x;
|
||||||
|
int const token_idx = blockIdx.x;
|
||||||
|
scale_type const scale = *scale_ptr;
|
||||||
|
azp_type const azp = *azp_ptr;
|
||||||
|
|
||||||
|
for (int i = tid; i < hidden_size; i += blockDim.x) {
|
||||||
|
auto const val = static_cast<float>(input[token_idx * hidden_size + i]);
|
||||||
|
auto const quant_val = int32_to_int8(float_to_int32_rn(val / scale) + azp);
|
||||||
|
out[token_idx * hidden_size + i] = quant_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename scalar_t, typename scale_type>
|
template <typename scalar_t, typename scale_type>
|
||||||
__global__ void dynamic_scaled_int8_quant_kernel(
|
__global__ void dynamic_scaled_int8_quant_kernel(
|
||||||
scalar_t const* __restrict__ input, int8_t* __restrict__ out,
|
scalar_t const* __restrict__ input, int8_t* __restrict__ out,
|
||||||
@@ -80,14 +155,68 @@ __global__ void dynamic_scaled_int8_quant_kernel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename scalar_t, typename scale_type, typename azp_type>
|
||||||
|
__global__ void dynamic_scaled_int8_azp_quant_kernel(
|
||||||
|
scalar_t const* __restrict__ input, int8_t* __restrict__ out,
|
||||||
|
scale_type* scale, azp_type* azp, const int hidden_size) {
|
||||||
|
int const token_idx = blockIdx.x;
|
||||||
|
|
||||||
|
// Scan for the min and max value for this token
|
||||||
|
float max_val = std::numeric_limits<float>::min();
|
||||||
|
float min_val = std::numeric_limits<float>::max();
|
||||||
|
for (int i = threadIdx.x; i < hidden_size; i += blockDim.x) {
|
||||||
|
auto val = static_cast<float>(input[token_idx * hidden_size + i]);
|
||||||
|
max_val = std::max(max_val, val);
|
||||||
|
min_val = std::min(min_val, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce the max and min values across the block
|
||||||
|
using BlockReduce = cub::BlockReduce<float, 1024>;
|
||||||
|
__shared__ typename BlockReduce::TempStorage reduceStorage;
|
||||||
|
max_val = BlockReduce(reduceStorage).Reduce(max_val, cub::Max{}, blockDim.x);
|
||||||
|
__syncthreads(); // Make sure min doesn't mess with max shared memory
|
||||||
|
min_val = BlockReduce(reduceStorage).Reduce(min_val, cub::Min{}, blockDim.x);
|
||||||
|
|
||||||
|
__shared__ scale_type scale_sh;
|
||||||
|
__shared__ azp_type azp_sh;
|
||||||
|
|
||||||
|
// Compute the scale and zero point and store them, only on the first thread
|
||||||
|
if (threadIdx.x == 0) {
|
||||||
|
float const scale_val = (max_val - min_val) / 255.0f;
|
||||||
|
// Use rounding to even (same as torch.round)
|
||||||
|
auto const azp_float = std::nearbyint(-128.0f - min_val / scale_val);
|
||||||
|
auto const azp_val = static_cast<azp_type>(azp_float);
|
||||||
|
|
||||||
|
// Store the scale and azp into shared and global
|
||||||
|
scale[token_idx] = scale_sh = scale_val;
|
||||||
|
azp[token_idx] = azp_sh = azp_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the scale and azp to be computed
|
||||||
|
__syncthreads();
|
||||||
|
|
||||||
|
float const scale_val = scale_sh;
|
||||||
|
azp_type const azp_val = azp_sh;
|
||||||
|
|
||||||
|
// Quantize the values
|
||||||
|
for (int i = threadIdx.x; i < hidden_size; i += blockDim.x) {
|
||||||
|
auto const val = static_cast<float>(input[token_idx * hidden_size + i]);
|
||||||
|
auto const quant_val =
|
||||||
|
int32_to_int8(float_to_int32_rn(val / scale_val) + azp_val);
|
||||||
|
out[token_idx * hidden_size + i] = quant_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace vllm
|
} // namespace vllm
|
||||||
|
|
||||||
void static_scaled_int8_quant(torch::Tensor& out, // [..., hidden_size]
|
void static_scaled_int8_quant(torch::Tensor& out, // [..., hidden_size]
|
||||||
torch::Tensor const& input, // [..., hidden_size]
|
torch::Tensor const& input, // [..., hidden_size]
|
||||||
torch::Tensor const& scale) {
|
torch::Tensor const& scale,
|
||||||
|
c10::optional<torch::Tensor> const& azp) {
|
||||||
TORCH_CHECK(input.is_contiguous());
|
TORCH_CHECK(input.is_contiguous());
|
||||||
TORCH_CHECK(out.is_contiguous());
|
TORCH_CHECK(out.is_contiguous());
|
||||||
TORCH_CHECK(scale.numel() == 1);
|
TORCH_CHECK(scale.numel() == 1);
|
||||||
|
TORCH_CHECK(!azp || azp->numel() == 1);
|
||||||
|
|
||||||
int const hidden_size = input.size(-1);
|
int const hidden_size = input.size(-1);
|
||||||
int const num_tokens = input.numel() / hidden_size;
|
int const num_tokens = input.numel() / hidden_size;
|
||||||
@@ -96,19 +225,29 @@ void static_scaled_int8_quant(torch::Tensor& out, // [..., hidden_size]
|
|||||||
const cudaStream_t stream = at::cuda::getCurrentCUDAStream();
|
const cudaStream_t stream = at::cuda::getCurrentCUDAStream();
|
||||||
VLLM_DISPATCH_FLOATING_TYPES(
|
VLLM_DISPATCH_FLOATING_TYPES(
|
||||||
input.scalar_type(), "static_scaled_int8_quant_kernel", [&] {
|
input.scalar_type(), "static_scaled_int8_quant_kernel", [&] {
|
||||||
vllm::static_scaled_int8_quant_kernel<scalar_t, float>
|
if (!azp) {
|
||||||
<<<grid, block, 0, stream>>>(input.data_ptr<scalar_t>(),
|
vllm::static_scaled_int8_quant_kernel<scalar_t, float>
|
||||||
out.data_ptr<int8_t>(),
|
<<<grid, block, 0, stream>>>(
|
||||||
scale.data_ptr<float>(), hidden_size);
|
input.data_ptr<scalar_t>(), out.data_ptr<int8_t>(),
|
||||||
|
scale.data_ptr<float>(), hidden_size);
|
||||||
|
} else {
|
||||||
|
vllm::static_scaled_int8_azp_quant_kernel<scalar_t, float, int32_t>
|
||||||
|
<<<grid, block, 0, stream>>>(
|
||||||
|
input.data_ptr<scalar_t>(), out.data_ptr<int8_t>(),
|
||||||
|
scale.data_ptr<float>(), azp->data_ptr<int32_t>(),
|
||||||
|
hidden_size);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void dynamic_scaled_int8_quant(
|
void dynamic_scaled_int8_quant(
|
||||||
torch::Tensor& out, // [..., hidden_size]
|
torch::Tensor& out, // [..., hidden_size]
|
||||||
torch::Tensor const& input, // [..., hidden_size]
|
torch::Tensor const& input, // [..., hidden_size]
|
||||||
torch::Tensor& scales) {
|
torch::Tensor& scales, c10::optional<torch::Tensor> const& azp) {
|
||||||
TORCH_CHECK(input.is_contiguous());
|
TORCH_CHECK(input.is_contiguous());
|
||||||
TORCH_CHECK(out.is_contiguous());
|
TORCH_CHECK(out.is_contiguous());
|
||||||
|
TORCH_CHECK(scales.is_contiguous());
|
||||||
|
TORCH_CHECK(!azp || azp->is_contiguous());
|
||||||
|
|
||||||
int const hidden_size = input.size(-1);
|
int const hidden_size = input.size(-1);
|
||||||
int const num_tokens = input.numel() / hidden_size;
|
int const num_tokens = input.numel() / hidden_size;
|
||||||
@@ -117,9 +256,17 @@ void dynamic_scaled_int8_quant(
|
|||||||
const cudaStream_t stream = at::cuda::getCurrentCUDAStream();
|
const cudaStream_t stream = at::cuda::getCurrentCUDAStream();
|
||||||
VLLM_DISPATCH_FLOATING_TYPES(
|
VLLM_DISPATCH_FLOATING_TYPES(
|
||||||
input.scalar_type(), "dynamic_scaled_int8_quant_kernel", [&] {
|
input.scalar_type(), "dynamic_scaled_int8_quant_kernel", [&] {
|
||||||
vllm::dynamic_scaled_int8_quant_kernel<scalar_t, float>
|
if (!azp) {
|
||||||
<<<grid, block, 0, stream>>>(input.data_ptr<scalar_t>(),
|
vllm::dynamic_scaled_int8_quant_kernel<scalar_t, float>
|
||||||
out.data_ptr<int8_t>(),
|
<<<grid, block, 0, stream>>>(
|
||||||
scales.data_ptr<float>(), hidden_size);
|
input.data_ptr<scalar_t>(), out.data_ptr<int8_t>(),
|
||||||
|
scales.data_ptr<float>(), hidden_size);
|
||||||
|
} else {
|
||||||
|
vllm::dynamic_scaled_int8_azp_quant_kernel<scalar_t, float, int32_t>
|
||||||
|
<<<grid, block, 0, stream>>>(
|
||||||
|
input.data_ptr<scalar_t>(), out.data_ptr<int8_t>(),
|
||||||
|
scales.data_ptr<float>(), azp->data_ptr<int32_t>(),
|
||||||
|
hidden_size);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -353,18 +353,47 @@ static __global__ void dequantize_block_iq3_s(const void * __restrict__ vx, dst_
|
|||||||
template<typename dst_t>
|
template<typename dst_t>
|
||||||
static __global__ void dequantize_block_iq1_s(const void * __restrict__ vx, dst_t * __restrict__ yy) {
|
static __global__ void dequantize_block_iq1_s(const void * __restrict__ vx, dst_t * __restrict__ yy) {
|
||||||
|
|
||||||
const int i = blockIdx.x;
|
const int64_t i = blockIdx.x;
|
||||||
const block_iq1_s * x = (const block_iq1_s *) vx;
|
const block_iq1_s * x = (const block_iq1_s *) vx;
|
||||||
|
|
||||||
const int tid = threadIdx.x;
|
const int64_t tid = threadIdx.x;
|
||||||
const int il = tid/8; // 0...3
|
const int64_t il = tid/8; // 0...3
|
||||||
const int ib = tid%8; // 0...7
|
const int64_t ib = tid%8; // 0...7
|
||||||
dst_t * y = yy + i*QK_K + 32*ib + 8*il;
|
dst_t * y = yy + i*QK_K + 32*ib + 8*il;
|
||||||
const int i8 = 4*ib+il;
|
const float delta = x[i].qh[ib] & 0x8000 ? -1 - IQ1S_DELTA : -1 + IQ1S_DELTA;
|
||||||
uint8_t h = x[i].scales[i8/2] >> 4*(i8%2);
|
const float d = __half2float(x[i].d) * (2*((x[i].qh[ib] >> 12) & 7) + 1);
|
||||||
const int8_t * grid = (const int8_t *)(iq1s_grid + (x[i].qs[i8] | ((h & 8) << 5)));
|
uint32_t grid32[2]; const int8_t * q = (const int8_t *)grid32;
|
||||||
const float d = __half2float(x[i].d) * (2*(h & 7) + 1);
|
grid32[0] = iq1s_grid_gpu[x[i].qs[4*ib+il] | (((x[i].qh[ib] >> 3*il) & 7) << 8)];
|
||||||
for (int j = 0; j < 8; ++j) y[j] = __float2half(d * grid[j]);
|
grid32[1] = (grid32[0] >> 4) & 0x0f0f0f0f;
|
||||||
|
grid32[0] &= 0x0f0f0f0f;
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
y[j] = __float2half(d * (q[j] + delta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename dst_t>
|
||||||
|
static __global__ void dequantize_block_iq1_m(const void * __restrict__ vx, dst_t * __restrict__ yy) {
|
||||||
|
|
||||||
|
const int64_t i = blockIdx.x;
|
||||||
|
const block_iq1_m * x = (const block_iq1_m *) vx;
|
||||||
|
|
||||||
|
const int64_t tid = threadIdx.x;
|
||||||
|
const int64_t il = tid/8; // 0...3
|
||||||
|
const int64_t ib = tid%8; // 0...7
|
||||||
|
dst_t * y = yy + i*QK_K + 32*ib + 8*il;
|
||||||
|
const uint16_t * sc = (const uint16_t *)x[i].scales;
|
||||||
|
iq1m_scale_t scale;
|
||||||
|
scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000);
|
||||||
|
const int64_t ib16 = 2*ib + il/2; // sc[ib16/4] >> 3*(ib16%4) -> sc[ib/2] >> 3*((2*ib+il/2)%4);
|
||||||
|
const float d = __half2float(scale.f16) * (2*((sc[ib16/4] >> 3*(ib16%4)) & 0x7) + 1);
|
||||||
|
const float delta = x[i].qh[2*ib+il/2] & (0x08 << 4*(il%2)) ? -1 - IQ1M_DELTA : -1 + IQ1M_DELTA;
|
||||||
|
uint32_t grid32[2]; const int8_t * q = (const int8_t *)grid32;
|
||||||
|
grid32[0] = iq1s_grid_gpu[x[i].qs[4*ib+il] | (((x[i].qh[2*ib+il/2] >> 4*(il%2)) & 7) << 8)];
|
||||||
|
grid32[1] = (grid32[0] >> 4) & 0x0f0f0f0f;
|
||||||
|
grid32[0] &= 0x0f0f0f0f;
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
y[j] = __float2half(d * (q[j] + delta));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename dst_t>
|
template<typename dst_t>
|
||||||
@@ -475,6 +504,12 @@ static void dequantize_row_iq1_s_cuda(const void * vx, dst_t * y, const int k, c
|
|||||||
dequantize_block_iq1_s<<<nb, 32, 0, stream>>>(vx, y);
|
dequantize_block_iq1_s<<<nb, 32, 0, stream>>>(vx, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename dst_t>
|
||||||
|
static void dequantize_row_iq1_m_cuda(const void * vx, dst_t * y, const int k, cudaStream_t stream) {
|
||||||
|
const int nb = k / QK_K;
|
||||||
|
dequantize_block_iq1_m<<<nb, 32, 0, stream>>>(vx, y);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename dst_t>
|
template<typename dst_t>
|
||||||
static void dequantize_row_iq4_nl_cuda(const void * vx, dst_t * y, const int k, cudaStream_t stream) {
|
static void dequantize_row_iq4_nl_cuda(const void * vx, dst_t * y, const int k, cudaStream_t stream) {
|
||||||
const int nb = (k + QK_K - 1) / QK_K;
|
const int nb = (k + QK_K - 1) / QK_K;
|
||||||
@@ -525,6 +560,8 @@ static to_fp16_cuda_t ggml_get_to_fp16_cuda(int64_t type) {
|
|||||||
return dequantize_row_iq2_s_cuda;
|
return dequantize_row_iq2_s_cuda;
|
||||||
case 23:
|
case 23:
|
||||||
return dequantize_row_iq4_xs_cuda;
|
return dequantize_row_iq4_xs_cuda;
|
||||||
|
case 29:
|
||||||
|
return dequantize_row_iq1_m_cuda;
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,14 +149,30 @@ typedef struct {
|
|||||||
uint8_t scales[IQ3S_N_SCALE];
|
uint8_t scales[IQ3S_N_SCALE];
|
||||||
} block_iq3_s;
|
} block_iq3_s;
|
||||||
|
|
||||||
|
// 1.5625 bpw
|
||||||
#define QR1_S 8
|
#define QR1_S 8
|
||||||
#define QI1_S (QK_K / (4*QR1_S))
|
#define QI1_S (QK_K / (4*QR1_S))
|
||||||
typedef struct {
|
typedef struct {
|
||||||
half d;
|
half d;
|
||||||
uint8_t qs[QK_K/8];
|
uint8_t qs[QK_K/8];
|
||||||
uint8_t scales[QK_K/16];
|
uint16_t qh[QK_K/32];
|
||||||
} block_iq1_s;
|
} block_iq1_s;
|
||||||
|
|
||||||
|
// 1.75 bpw
|
||||||
|
#define QR1_M 8
|
||||||
|
#define QI1_M (QK_K / (4*QR1_M))
|
||||||
|
typedef struct {
|
||||||
|
uint8_t qs[QK_K/8]; // grid index, low 8 bits
|
||||||
|
uint8_t qh[QK_K/16]; // grid index, high 3 bits + grid shift bit (for two groups of 8)
|
||||||
|
uint8_t scales[QK_K/32]; // 3-bit block scales (4-bit if QK_K == 64)
|
||||||
|
} block_iq1_m;
|
||||||
|
|
||||||
|
// Used by IQ1_M quants
|
||||||
|
typedef union {
|
||||||
|
half f16;
|
||||||
|
uint16_t u16;
|
||||||
|
} iq1m_scale_t;
|
||||||
|
|
||||||
#define QK4_NL 32
|
#define QK4_NL 32
|
||||||
#define QR4_NL 2
|
#define QR4_NL 2
|
||||||
#define QI4_NL (QK4_NL / (4*QR4_NL))
|
#define QI4_NL (QK4_NL / (4*QR4_NL))
|
||||||
@@ -733,135 +749,265 @@ static const __device__ uint32_t iq3xs_grid[512] = {
|
|||||||
0x3e240c1c, 0x3e241404, 0x3e242c04, 0x3e2c1414, 0x3e2c2414, 0x3e340414, 0x3e341c0c, 0x3e3e0404,
|
0x3e240c1c, 0x3e241404, 0x3e242c04, 0x3e2c1414, 0x3e2c2414, 0x3e340414, 0x3e341c0c, 0x3e3e0404,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __device__ uint64_t iq1s_grid[512] = {
|
#define IQ1S_DELTA 0.125f
|
||||||
0xffffffffffff0101, 0xffffffffff01ff00, 0xffffffffff010100, 0xffffffff00000000,
|
#define IQ1M_DELTA 0.125f
|
||||||
0xffffffff01ff00ff, 0xffffffff01ff0001, 0xffffffff0101ffff, 0xffffffff0101ff01,
|
static const __device__ uint64_t iq1s_grid_gpu[2048] = {
|
||||||
0xffffff00ff000000, 0xffffff000000ff00, 0xffffff00000000ff, 0xffffff0000000100,
|
0x00000000, 0x00000002, 0x00000101, 0x00000200, 0x00000202, 0x00010001, 0x00010101, 0x00020000,
|
||||||
0xffffff0000010000, 0xffffff0001000000, 0xffffff01ffff00ff, 0xffffff01ff01ff00,
|
0x00020002, 0x00020200, 0x00020202, 0x01000101, 0x01010001, 0x01010100, 0x01010102, 0x01020101,
|
||||||
0xffffff01ff010100, 0xffffff0100000001, 0xffffff0101ffff00, 0xffffff0101ff0101,
|
0x02000000, 0x02000002, 0x02000200, 0x02000202, 0x02010101, 0x02020000, 0x02020002, 0x02020200,
|
||||||
0xffffff0101010100, 0xffff00ffff00ff01, 0xffff00ffff0000ff, 0xffff00ff00ff0100,
|
0x02020202, 0x00000110, 0x00000111, 0x00010011, 0x00010110, 0x00010112, 0x00010211, 0x00010212,
|
||||||
0xffff00ff0100ff00, 0xffff00ff010001ff, 0xffff0000ff0101ff, 0xffff000000ffff00,
|
0x00020111, 0x01000011, 0x01000112, 0x01000211, 0x01010012, 0x01010111, 0x01010212, 0x01020011,
|
||||||
0xffff000000000000, 0xffff00000001ff01, 0xffff000001000101, 0xffff0000010100ff,
|
0x01020110, 0x01020112, 0x01020210, 0x02000111, 0x02010011, 0x02010110, 0x02010112, 0x02020111,
|
||||||
0xffff0001ffff0100, 0xffff00010000ff00, 0xffff000100010101, 0xffff000101000000,
|
0x00000020, 0x00000022, 0x00000220, 0x00000222, 0x00010121, 0x00020020, 0x00020022, 0x00020220,
|
||||||
0xffff01ffffff0000, 0xffff01ffff01ffff, 0xffff01ffff010100, 0xffff01ff00000000,
|
0x00020222, 0x01000121, 0x01010021, 0x01010221, 0x01020120, 0x01020221, 0x02000020, 0x02000022,
|
||||||
0xffff01ff01ffffff, 0xffff01ff01ff0001, 0xffff01ff0101ffff, 0xffff01ff01010001,
|
0x02000220, 0x02000222, 0x02010021, 0x02010121, 0x02010221, 0x02020020, 0x02020022, 0x02020220,
|
||||||
0xffff0100ffffff01, 0xffff01000000ffff, 0xffff010000000100, 0xffff010001ff01ff,
|
0x02020222, 0x00011001, 0x00011100, 0x00011102, 0x00021101, 0x01001001, 0x01001201, 0x01011101,
|
||||||
0xffff010001000000, 0xffff0101ff000000, 0xffff0101000101ff, 0xffff010101ffff01,
|
0x01011202, 0x01021100, 0x01021101, 0x02011001, 0x02011201, 0x02021101, 0x00001011, 0x00001110,
|
||||||
0xffff01010101ff00, 0xff00ffffff000000, 0xff00ffff00ffff00, 0xff00ffff00000001,
|
0x00001111, 0x00001112, 0x00011111, 0x00011210, 0x00011212, 0x00021211, 0x01001010, 0x01001111,
|
||||||
0xff00ffff000001ff, 0xff00ffff01010000, 0xff00ff00ffff0000, 0xff00ff00ff00ff00,
|
0x01001212, 0x01011010, 0x01011011, 0x01011110, 0x01011111, 0x01011112, 0x01011211, 0x01021010,
|
||||||
0xff00ff00ff0000ff, 0xff00ff00ff000100, 0xff00ff00ff010001, 0xff00ff0000ff0001,
|
0x01021012, 0x01021111, 0x01021210, 0x01021212, 0x02001011, 0x02011011, 0x02011111, 0x02011210,
|
||||||
0xff00ff000000ffff, 0xff00ff0000000000, 0xff00ff000001ff00, 0xff00ff0000010100,
|
0x02011212, 0x02021011, 0x02021110, 0x02021111, 0x02021112, 0x02021211, 0x00011120, 0x00011221,
|
||||||
0xff00ff0001ff0000, 0xff00ff000100ff00, 0xff00ff0001000100, 0xff00ff01ff000000,
|
0x01001021, 0x01001120, 0x01011020, 0x01011022, 0x01011121, 0x01011220, 0x01021020, 0x01021021,
|
||||||
0xff00ff0100ff0000, 0xff00ff01000001ff, 0xff00ff0101010001, 0xff0000ff00000000,
|
0x01021122, 0x01021221, 0x02001121, 0x02011021, 0x02011120, 0x02011221, 0x00002000, 0x00002002,
|
||||||
0xff0000ff0001ff00, 0xff0000ff00010100, 0xff000000ffff0101, 0xff000000ff000000,
|
0x00002200, 0x00002202, 0x00012101, 0x00022000, 0x00022002, 0x00022200, 0x00022202, 0x01002101,
|
||||||
0xff000000ff01ff00, 0xff00000000ff0000, 0xff0000000000ff00, 0xff000000000000ff,
|
0x01012001, 0x01012102, 0x01022101, 0x02002000, 0x02002002, 0x02002200, 0x02002202, 0x02012101,
|
||||||
0xff00000000000000, 0xff00000000000001, 0xff00000000000100, 0xff0000000001ffff,
|
0x02022000, 0x02022002, 0x02022200, 0x02022202, 0x00002111, 0x00012011, 0x00012110, 0x00012211,
|
||||||
0xff00000000010000, 0xff00000001000000, 0xff00000001010100, 0xff000001ff00ff01,
|
0x00022110, 0x00022111, 0x01002011, 0x01012010, 0x01012011, 0x01012111, 0x01022011, 0x01022110,
|
||||||
0xff000001ff0100ff, 0xff00000100000000, 0xff0000010001ff00, 0xff00000101ff0100,
|
0x01022211, 0x02012011, 0x02012110, 0x02012112, 0x02012211, 0x02022111, 0x00002020, 0x00002022,
|
||||||
0xff0000010100ff00, 0xff0001ff00ff00ff, 0xff0001ff00000101, 0xff0001ff000100ff,
|
0x00002220, 0x00002222, 0x00012121, 0x00022020, 0x00022022, 0x00022220, 0x00022222, 0x01002121,
|
||||||
0xff0001ff01000000, 0xff000100ff0001ff, 0xff0001000000ff01, 0xff00010000000000,
|
0x01012021, 0x01012221, 0x01022021, 0x01022121, 0x02002020, 0x02002022, 0x02002121, 0x02002220,
|
||||||
0xff00010000010001, 0xff00010000010100, 0xff00010001ffff00, 0xff00010001ff0101,
|
0x02002222, 0x02012121, 0x02022020, 0x02022022, 0x02022220, 0x02022222, 0x00110000, 0x00110001,
|
||||||
0xff00010001010000, 0xff000101ffffffff, 0xff000101ff000101, 0xff00010101ff00ff,
|
0x00110100, 0x00110201, 0x00120100, 0x00120101, 0x01100001, 0x01100100, 0x01110000, 0x01110101,
|
||||||
0xff00010101000001, 0xff000101010100ff, 0xff01ffffff000101, 0xff01ffffff01ffff,
|
0x01110200, 0x01120001, 0x01120100, 0x01120101, 0x01120201, 0x02110001, 0x02110100, 0x02110102,
|
||||||
0xff01ffffff01ff01, 0xff01ffffff0101ff, 0xff01ffff00000000, 0xff01ffff01ff0001,
|
0x02120001, 0x02120101, 0x00100011, 0x00100110, 0x00100112, 0x00100211, 0x00110010, 0x00110012,
|
||||||
0xff01ffff0101ff01, 0xff01ff00ff000000, 0xff01ff0000ff0100, 0xff01ff000000ff01,
|
0x00110111, 0x00110210, 0x00120011, 0x00120110, 0x00120211, 0x01100111, 0x01100212, 0x01110010,
|
||||||
0xff01ff0000010000, 0xff01ff00010000ff, 0xff01ff01ff01ff00, 0xff01ff0100000101,
|
0x01110011, 0x01110012, 0x01110110, 0x01110111, 0x01110112, 0x01110211, 0x01120010, 0x01120111,
|
||||||
0xff0100ffffff0000, 0xff0100ffff010000, 0xff0100ff01ff00ff, 0xff0100ff01000100,
|
0x02100110, 0x02110012, 0x02110111, 0x02120011, 0x02120110, 0x00110021, 0x00110120, 0x00110122,
|
||||||
0xff0100ff010100ff, 0xff010000ffffff01, 0xff01000000000000, 0xff0100000101ff00,
|
0x00120121, 0x01100020, 0x01100122, 0x01100221, 0x01110022, 0x01110121, 0x01110220, 0x01110222,
|
||||||
0xff010001ffff00ff, 0xff010001ff000100, 0xff01000100ffff00, 0xff01000100010001,
|
0x01120120, 0x01120122, 0x02100121, 0x02110021, 0x02110120, 0x02110122, 0x02120121, 0x00101001,
|
||||||
0xff01000101ff0001, 0xff010001010001ff, 0xff0101ffffffffff, 0xff0101ffff01ffff,
|
0x00101102, 0x00101201, 0x00111100, 0x00111101, 0x00111200, 0x00111201, 0x00121001, 0x00121102,
|
||||||
0xff0101ffff010101, 0xff0101ff0000ff00, 0xff0101ff01010001, 0xff010100ff000000,
|
0x01101001, 0x01101101, 0x01101102, 0x01101200, 0x01101202, 0x01111001, 0x01111100, 0x01111101,
|
||||||
0xff010100ff01ff01, 0xff01010000ff0001, 0xff01010000000100, 0xff01010001000000,
|
0x01111102, 0x01111201, 0x01121002, 0x01121101, 0x01121200, 0x02101100, 0x02101201, 0x02111000,
|
||||||
0xff0101010100ffff, 0x00ffffff0000ff01, 0x00ffffff000000ff, 0x00ffffff00000100,
|
0x02111100, 0x02111101, 0x02111200, 0x02111201, 0x02111202, 0x02121001, 0x02121100, 0x02121101,
|
||||||
0x00ffffff00010000, 0x00ffff00ffff0001, 0x00ffff00ff0000ff, 0x00ffff00ff000100,
|
0x02121201, 0x00101012, 0x00101111, 0x00101212, 0x00111011, 0x00111110, 0x00111111, 0x00111112,
|
||||||
0x00ffff0000000000, 0x00ffff0001000100, 0x00ffff0001010001, 0x00ffff01ff00ff01,
|
0x00111211, 0x00121010, 0x00121012, 0x00121111, 0x00121210, 0x00121212, 0x01101011, 0x01101110,
|
||||||
0x00ffff0100ff0100, 0x00ffff010000ff00, 0x00ffff01000100ff, 0x00ffff0101ff00ff,
|
0x01101111, 0x01101112, 0x01111011, 0x01111012, 0x01111110, 0x01111111, 0x01111112, 0x01111211,
|
||||||
0x00ffff010101ff00, 0x00ff00ffffffffff, 0x00ff00ffffff01ff, 0x00ff00ffff000101,
|
0x01111212, 0x01121011, 0x01121110, 0x01121111, 0x01121112, 0x01121211, 0x02101010, 0x02101012,
|
||||||
0x00ff00ff00000000, 0x00ff00ff000101ff, 0x00ff00ff01010101, 0x00ff0000ff000000,
|
0x02101110, 0x02101111, 0x02101210, 0x02101212, 0x02111010, 0x02111011, 0x02111110, 0x02111111,
|
||||||
0x00ff0000ff01ffff, 0x00ff000000ff0000, 0x00ff00000000ff00, 0x00ff0000000000ff,
|
0x02111112, 0x02111211, 0x02111212, 0x02121010, 0x02121012, 0x02121111, 0x00101021, 0x00101120,
|
||||||
0x00ff000000000000, 0x00ff000000000001, 0x00ff000000000100, 0x00ff000000010000,
|
0x00101121, 0x00101122, 0x00111121, 0x00111122, 0x00111220, 0x00111222, 0x00121021, 0x00121122,
|
||||||
0x00ff000001ffff01, 0x00ff000001000000, 0x00ff0001ff000101, 0x00ff000100ffffff,
|
0x01101020, 0x01101022, 0x01101120, 0x01101121, 0x01101220, 0x01101222, 0x01111021, 0x01111121,
|
||||||
0x00ff000100000000, 0x00ff0001010001ff, 0x00ff01ffff000000, 0x00ff01ff0001ff00,
|
0x01111122, 0x01111220, 0x01111221, 0x01121021, 0x01121120, 0x01121121, 0x01121220, 0x01121221,
|
||||||
0x00ff01ff01ff0100, 0x00ff0100ff01ff01, 0x00ff010000ff00ff, 0x00ff010000ff0101,
|
0x01121222, 0x02101122, 0x02101222, 0x02111022, 0x02111121, 0x02121120, 0x02121221, 0x00112001,
|
||||||
0x00ff010000000000, 0x00ff010000010101, 0x00ff01000100ff00, 0x00ff010001010000,
|
0x00112102, 0x00122101, 0x01102001, 0x01102100, 0x01102102, 0x01102201, 0x01112000, 0x01112101,
|
||||||
0x00ff0101ffffff00, 0x00ff01010000ff01, 0x00ff010100000100, 0x00ff010101ff0000,
|
0x01112200, 0x01112202, 0x01122000, 0x01122001, 0x01122100, 0x01122102, 0x01122201, 0x02102101,
|
||||||
0x0000ffffffff0100, 0x0000ffffff00ff00, 0x0000ffffff0000ff, 0x0000ffffff010000,
|
0x02112001, 0x02112100, 0x02122101, 0x00112010, 0x00112012, 0x00112111, 0x00112212, 0x00122011,
|
||||||
0x0000ffff00000000, 0x0000ffff00010101, 0x0000ffff01ffff01, 0x0000ffff01000100,
|
0x00122111, 0x01102012, 0x01102110, 0x01102111, 0x01102210, 0x01112011, 0x01112110, 0x01112111,
|
||||||
0x0000ff00ff000000, 0x0000ff00ff01ff00, 0x0000ff00ff0101ff, 0x0000ff0000ff0000,
|
0x01112112, 0x01112211, 0x01112212, 0x01122010, 0x01122111, 0x01122212, 0x02102211, 0x02112011,
|
||||||
0x0000ff000000ff00, 0x0000ff00000000ff, 0x0000ff0000000000, 0x0000ff0000000001,
|
0x02112012, 0x02112111, 0x02112210, 0x02122011, 0x02122112, 0x02122211, 0x00102221, 0x00112122,
|
||||||
0x0000ff0000000100, 0x0000ff0000010000, 0x0000ff0001ffffff, 0x0000ff0001ff01ff,
|
0x00122120, 0x00122122, 0x01102120, 0x01102122, 0x01102221, 0x01112020, 0x01112022, 0x01112121,
|
||||||
0x0000ff0001000000, 0x0000ff000101ffff, 0x0000ff01ffff0101, 0x0000ff01ff010000,
|
0x01112220, 0x01122021, 0x01122122, 0x01122221, 0x02102121, 0x02112021, 0x02112122, 0x02112222,
|
||||||
0x0000ff0100000000, 0x0000ff0101000101, 0x000000ffffff0001, 0x000000ffff000000,
|
0x00200000, 0x00200002, 0x00200200, 0x00200202, 0x00210101, 0x00220000, 0x00220002, 0x00220101,
|
||||||
0x000000ff00ff0000, 0x000000ff0000ff00, 0x000000ff000000ff, 0x000000ff00000000,
|
0x00220200, 0x00220202, 0x01200101, 0x01210001, 0x01210201, 0x01220001, 0x01220101, 0x02200000,
|
||||||
0x000000ff00000001, 0x000000ff00000100, 0x000000ff00010000, 0x000000ff01000000,
|
0x02200002, 0x02200200, 0x02200202, 0x02210101, 0x02220000, 0x02220002, 0x02220101, 0x02220200,
|
||||||
0x000000ff0101ff00, 0x00000000ffff0000, 0x00000000ff00ff00, 0x00000000ff0000ff,
|
0x02220202, 0x00200111, 0x00210011, 0x00210110, 0x00210211, 0x00220111, 0x01200012, 0x01200110,
|
||||||
0x00000000ff000000, 0x00000000ff000001, 0x00000000ff000100, 0x00000000ff010000,
|
0x01200211, 0x01210111, 0x01210210, 0x01210212, 0x01220011, 0x01220110, 0x01220111, 0x01220112,
|
||||||
0x0000000000ffff00, 0x0000000000ff00ff, 0x0000000000ff0000, 0x0000000000ff0001,
|
0x02200111, 0x02210010, 0x02210112, 0x02210211, 0x02220111, 0x00200021, 0x00200220, 0x00200222,
|
||||||
0x0000000000ff0100, 0x000000000000ffff, 0x000000000000ff00, 0x000000000000ff01,
|
0x00210021, 0x00210121, 0x00220020, 0x00220022, 0x00220220, 0x00220222, 0x01200121, 0x01210021,
|
||||||
0x00000000000000ff, 0x0000000000000001, 0x00000000000001ff, 0x0000000000000100,
|
0x01210122, 0x01210221, 0x01220121, 0x02200021, 0x02200220, 0x02200222, 0x02210021, 0x02210121,
|
||||||
0x0000000000000101, 0x000000000001ff00, 0x00000000000100ff, 0x0000000000010000,
|
0x02220020, 0x02220022, 0x02220220, 0x02220222, 0x00201101, 0x00211100, 0x00211102, 0x00211201,
|
||||||
0x0000000000010001, 0x0000000000010100, 0x0000000001ff0000, 0x000000000100ff00,
|
0x00221101, 0x01201100, 0x01201101, 0x01201102, 0x01201201, 0x01211002, 0x01211101, 0x01211200,
|
||||||
0x00000000010000ff, 0x0000000001000000, 0x0000000001000001, 0x0000000001000100,
|
0x01211202, 0x01221102, 0x02201101, 0x02211001, 0x02211100, 0x02211201, 0x02221001, 0x02221101,
|
||||||
0x0000000001010000, 0x00000001ffff01ff, 0x00000001ff000000, 0x0000000100ff0000,
|
0x00201211, 0x00211111, 0x00221011, 0x00221211, 0x01201010, 0x01201111, 0x01201210, 0x01211011,
|
||||||
0x000000010000ff00, 0x00000001000000ff, 0x0000000100000000, 0x0000000100000001,
|
0x01211110, 0x01211111, 0x01211211, 0x01221012, 0x01221111, 0x01221210, 0x02201211, 0x02211010,
|
||||||
0x0000000100000100, 0x0000000100010000, 0x0000000101000000, 0x000001ffff00ff00,
|
0x02211110, 0x02211111, 0x02211210, 0x02211212, 0x02221011, 0x02221110, 0x02221112, 0x02221211,
|
||||||
0x000001ffff010001, 0x000001ffff0101ff, 0x000001ff00ffff01, 0x000001ff0000ffff,
|
0x00201121, 0x00211020, 0x00211022, 0x00211221, 0x00221121, 0x01201021, 0x01201221, 0x01211121,
|
||||||
0x000001ff00000000, 0x000001ff010000ff, 0x000001ff01010100, 0x00000100ffff0100,
|
0x01221020, 0x01221021, 0x01221221, 0x02201120, 0x02201122, 0x02211020, 0x02211222, 0x00202000,
|
||||||
0x00000100ff000000, 0x0000010000ff0000, 0x000001000000ff00, 0x00000100000000ff,
|
0x00202002, 0x00202200, 0x00202202, 0x00212101, 0x00222000, 0x00222002, 0x00222200, 0x00222202,
|
||||||
0x0000010000000000, 0x0000010000000001, 0x0000010000000100, 0x0000010000010000,
|
0x01202101, 0x01212001, 0x01212100, 0x01222101, 0x02202000, 0x02202002, 0x02202200, 0x02202202,
|
||||||
0x0000010001000000, 0x000001000101ff01, 0x00000101ffff0001, 0x00000101ff01ffff,
|
0x02222000, 0x02222002, 0x02222200, 0x02222202, 0x00202211, 0x00212011, 0x00212110, 0x00212211,
|
||||||
0x0000010100000000, 0x0000010101010100, 0x0001ffffff000000, 0x0001ffff00ffffff,
|
0x00222111, 0x01202112, 0x01202211, 0x01212012, 0x01212111, 0x01222011, 0x01222110, 0x01222112,
|
||||||
0x0001ffff00000100, 0x0001ffff0001ff00, 0x0001ffff01000000, 0x0001ff00ffffff00,
|
0x01222211, 0x02202111, 0x02212010, 0x02212112, 0x02212211, 0x02222110, 0x02222111, 0x00202020,
|
||||||
0x0001ff00ffff01ff, 0x0001ff00ff010000, 0x0001ff0000000000, 0x0001ff0000010001,
|
0x00202022, 0x00202220, 0x00202222, 0x00222020, 0x00222022, 0x00222220, 0x00222222, 0x01202121,
|
||||||
0x0001ff0001ff0000, 0x0001ff0001010100, 0x0001ff01ff0000ff, 0x0001ff01ff000001,
|
0x01212021, 0x01212122, 0x01212221, 0x01222121, 0x02202020, 0x02202022, 0x02202220, 0x02202222,
|
||||||
0x0001ff0100ffffff, 0x0001ff010001ffff, 0x0001ff01000101ff, 0x0001ff010100ff01,
|
0x02212121, 0x02222020, 0x02222022, 0x02222220, 0x02222222, 0x10000101, 0x10010001, 0x10010102,
|
||||||
0x000100ffff00ffff, 0x000100ffff00ff01, 0x000100ffff000100, 0x000100ff00000000,
|
0x10020101, 0x11000201, 0x11010002, 0x11010101, 0x11010200, 0x11010202, 0x11020001, 0x11020100,
|
||||||
0x000100ff000101ff, 0x000100ff01ff0101, 0x000100ff0100ffff, 0x000100ff01010101,
|
0x11020102, 0x12010100, 0x12010201, 0x12020001, 0x12020102, 0x10000010, 0x10000011, 0x10000110,
|
||||||
0x00010000ff000000, 0x00010000ff010100, 0x0001000000ff0000, 0x000100000000ff00,
|
0x10000112, 0x10000211, 0x10010012, 0x10010111, 0x10010112, 0x10010210, 0x10010212, 0x10020011,
|
||||||
0x00010000000000ff, 0x0001000000000000, 0x0001000000000001, 0x0001000000000100,
|
0x10020112, 0x10020211, 0x11000111, 0x11000210, 0x11000212, 0x11010011, 0x11010110, 0x11010111,
|
||||||
0x0001000000010000, 0x0001000001ffff01, 0x0001000001000000, 0x0001000100ff0101,
|
0x11010112, 0x11010211, 0x11010212, 0x11020111, 0x11020210, 0x11020212, 0x12000011, 0x12000110,
|
||||||
0x0001000100000000, 0x00010001010100ff, 0x000101ffffff01ff, 0x000101ffffff0101,
|
0x12000112, 0x12010010, 0x12010012, 0x12010111, 0x12020010, 0x12020011, 0x12020012, 0x10000121,
|
||||||
0x000101ff00010000, 0x000101ff01ff0000, 0x000101ff0100ff01, 0x00010100ffff0000,
|
0x10010021, 0x10010120, 0x10010122, 0x10020121, 0x11000021, 0x11010022, 0x11010121, 0x11010222,
|
||||||
0x0001010000000000, 0x000101000001ffff, 0x0001010000010101, 0x00010100010001ff,
|
0x11020120, 0x11020221, 0x12000221, 0x12010120, 0x12020121, 0x10001001, 0x10011101, 0x10011201,
|
||||||
0x00010101ff00ff00, 0x00010101ff010001, 0x0001010100ffffff, 0x0001010100ff01ff,
|
0x10021201, 0x11001101, 0x11001200, 0x11001202, 0x11011001, 0x11011100, 0x11011101, 0x11011102,
|
||||||
0x00010101000101ff, 0x0001010101ff0000, 0x000101010100ff01, 0x0001010101000101,
|
0x11021001, 0x11021002, 0x11021101, 0x11021200, 0x11021202, 0x12001001, 0x12001102, 0x12001201,
|
||||||
0x01ffffffffff0101, 0x01ffffffff01ffff, 0x01ffffffff01ff01, 0x01ffffffff0101ff,
|
0x12011000, 0x12011002, 0x12011101, 0x12021000, 0x12021001, 0x12021201, 0x10001011, 0x10001012,
|
||||||
0x01ffffffff010101, 0x01ffffff00000000, 0x01ffffff01ff01ff, 0x01ffffff01000101,
|
0x10001111, 0x10001212, 0x10011011, 0x10011110, 0x10011111, 0x10011112, 0x10011211, 0x10021010,
|
||||||
0x01ffffff0101ff01, 0x01ffffff010100ff, 0x01ffff000000ff00, 0x01ffff0000000001,
|
0x10021111, 0x10021212, 0x11001011, 0x11001110, 0x11001111, 0x11001112, 0x11001211, 0x11011010,
|
||||||
0x01ffff00000001ff, 0x01ffff0000010000, 0x01ffff0001ff0000, 0x01ffff01ffffffff,
|
0x11011011, 0x11011110, 0x11011111, 0x11011112, 0x11011210, 0x11011211, 0x11021011, 0x11021110,
|
||||||
0x01ffff01ffff01ff, 0x01ffff01ff000000, 0x01ffff01ff01ffff, 0x01ffff01ff0101ff,
|
0x11021111, 0x11021112, 0x11021211, 0x12001012, 0x12001110, 0x12001111, 0x12001210, 0x12011011,
|
||||||
0x01ffff010100ffff, 0x01ff00ffffff0000, 0x01ff00ffff010000, 0x01ff00ff00ffff01,
|
0x12011110, 0x12011111, 0x12011112, 0x12011211, 0x12011212, 0x12021111, 0x12021210, 0x12021212,
|
||||||
0x01ff0000ff0000ff, 0x01ff000000000000, 0x01ff00000001ff01, 0x01ff000001ffffff,
|
0x10001021, 0x10001121, 0x10001221, 0x10011120, 0x10011121, 0x10011220, 0x10011222, 0x10021021,
|
||||||
0x01ff000001010100, 0x01ff0001ffffff01, 0x01ff0001ff010001, 0x01ff000101ff0100,
|
0x10021120, 0x10021221, 0x11001020, 0x11001022, 0x11001121, 0x11001220, 0x11011020, 0x11011021,
|
||||||
0x01ff000101000001, 0x01ff0001010100ff, 0x01ff01ffff00ffff, 0x01ff01ff00010001,
|
0x11011022, 0x11011121, 0x11011122, 0x11011221, 0x11021022, 0x11021121, 0x11021220, 0x12001021,
|
||||||
0x01ff01ff01000000, 0x01ff01ff010101ff, 0x01ff0100ff000001, 0x01ff010000ffff00,
|
0x12001121, 0x12001222, 0x12011120, 0x12011121, 0x12021021, 0x12021120, 0x12021122, 0x10002101,
|
||||||
0x01ff010000000100, 0x01ff010001ff01ff, 0x01ff01000101ffff, 0x01ff0101ffff00ff,
|
0x10012001, 0x10012101, 0x10012202, 0x10022101, 0x11002002, 0x11002201, 0x11012000, 0x11012101,
|
||||||
0x01ff0101ffff0101, 0x01ff0101ff0101ff, 0x01ff010100010000, 0x0100ffff00ff00ff,
|
0x11012200, 0x11022001, 0x11022100, 0x11022102, 0x11022201, 0x12002101, 0x12012001, 0x12012100,
|
||||||
0x0100ffff00ff0001, 0x0100ffff00000100, 0x0100ffff0100ff00, 0x0100ff00ffff0000,
|
0x12012102, 0x12012201, 0x12022101, 0x10002011, 0x10002111, 0x10002112, 0x10002212, 0x10012010,
|
||||||
0x0100ff00ff00ffff, 0x0100ff00ff00ff01, 0x0100ff00ff000100, 0x0100ff00ff010000,
|
0x10012110, 0x10012111, 0x10012210, 0x10022011, 0x10022110, 0x10022112, 0x11002010, 0x11002111,
|
||||||
0x0100ff0000000000, 0x0100ff00000100ff, 0x0100ff0001ff0101, 0x0100ff0001010101,
|
0x11002212, 0x11012011, 0x11012012, 0x11012110, 0x11012111, 0x11012112, 0x11012211, 0x11022010,
|
||||||
0x0100ff0100ff00ff, 0x0100ff0100ff0001, 0x0100ff0100000100, 0x0100ff0100010001,
|
0x11022012, 0x11022111, 0x11022112, 0x11022212, 0x12002112, 0x12002211, 0x12012012, 0x12012111,
|
||||||
0x0100ff0101000000, 0x010000ffff00ff00, 0x010000ff0000ffff, 0x010000ff00000000,
|
0x12012112, 0x12012210, 0x12022011, 0x12022110, 0x12022112, 0x12022211, 0x10012122, 0x11002120,
|
||||||
0x010000ff010001ff, 0x010000ff01010001, 0x01000000ffffff00, 0x01000000ffff0101,
|
0x11002122, 0x11002221, 0x11012121, 0x11012220, 0x11012222, 0x11022120, 0x11022221, 0x12012120,
|
||||||
0x01000000ff000000, 0x01000000ff0100ff, 0x01000000ff010101, 0x0100000000ff0000,
|
0x12022121, 0x10100001, 0x10100100, 0x10100101, 0x10100102, 0x10100201, 0x10110002, 0x10110101,
|
||||||
0x010000000000ff00, 0x01000000000000ff, 0x0100000000000000, 0x0100000000000001,
|
0x10110202, 0x10120001, 0x10120100, 0x10120201, 0x11100000, 0x11100101, 0x11100200, 0x11110001,
|
||||||
0x0100000000000100, 0x0100000000010000, 0x0100000001000000, 0x0100000100000000,
|
0x11110100, 0x11110101, 0x11110102, 0x11110201, 0x11120101, 0x11120200, 0x12100102, 0x12100201,
|
||||||
0x01000001000101ff, 0x0100000101ffff01, 0x010001ffff000101, 0x010001ff00ff0100,
|
0x12110101, 0x12110200, 0x12120000, 0x12120001, 0x12120102, 0x12120201, 0x10100111, 0x10100210,
|
||||||
0x010001ff0000ff00, 0x010001ff000100ff, 0x010001ff01ffffff, 0x01000100ffff0000,
|
0x10100211, 0x10100212, 0x10110011, 0x10110110, 0x10110111, 0x10110112, 0x10110210, 0x10110211,
|
||||||
0x01000100ff0001ff, 0x0100010000000000, 0x010001000001ff00, 0x0100010001ff0000,
|
0x10120010, 0x10120111, 0x10120112, 0x10120210, 0x10120212, 0x11100011, 0x11100110, 0x11100111,
|
||||||
0x01000100010000ff, 0x0100010001000101, 0x01000101ff00ff01, 0x0100010100ff0100,
|
0x11100112, 0x11100211, 0x11110010, 0x11110011, 0x11110012, 0x11110110, 0x11110111, 0x11110112,
|
||||||
0x010001010000ffff, 0x0100010101010001, 0x0101ffffffff0101, 0x0101ffffff0001ff,
|
0x11110210, 0x11110211, 0x11110212, 0x11120011, 0x11120110, 0x11120111, 0x11120112, 0x11120211,
|
||||||
0x0101ffffff01ffff, 0x0101ffffff010101, 0x0101ffff00000000, 0x0101ffff0101ffff,
|
0x12100012, 0x12100111, 0x12110011, 0x12110110, 0x12110111, 0x12110112, 0x12110211, 0x12120010,
|
||||||
0x0101ffff010101ff, 0x0101ff00ff000000, 0x0101ff0000ff0100, 0x0101ff000000ff00,
|
0x12120111, 0x12120212, 0x10100021, 0x10100122, 0x10110022, 0x10110121, 0x10110222, 0x10120021,
|
||||||
0x0101ff0000010000, 0x0101ff00010000ff, 0x0101ff0001000001, 0x0101ff01ff010101,
|
0x10120120, 0x11100022, 0x11100121, 0x11100222, 0x11110021, 0x11110120, 0x11110121, 0x11110122,
|
||||||
0x0101ff0100000000, 0x0101ff010101ff00, 0x010100ffffff0000, 0x010100ffff010000,
|
0x11110221, 0x11120022, 0x11120121, 0x12100121, 0x12110020, 0x12110022, 0x12110121, 0x12110221,
|
||||||
0x010100ff00ff01ff, 0x010100ff000000ff, 0x010100ff00000101, 0x010100ff01ffff00,
|
0x12110222, 0x12120120, 0x10101100, 0x10101101, 0x10111001, 0x10111100, 0x10111101, 0x10111102,
|
||||||
0x01010000ffffff01, 0x01010000ff000100, 0x01010000ff01ff01, 0x0101000000000000,
|
0x10111200, 0x10111201, 0x10121001, 0x10121101, 0x10121200, 0x10121202, 0x11101001, 0x11101100,
|
||||||
0x01010000000100ff, 0x010100000101ff01, 0x01010001ffff0000, 0x01010001ff00ffff,
|
0x11101101, 0x11101102, 0x11101201, 0x11101202, 0x11111000, 0x11111001, 0x11111100, 0x11111101,
|
||||||
0x01010001ff010000, 0x0101000101ffffff, 0x0101000101ff01ff, 0x0101000101010101,
|
0x11111102, 0x11111200, 0x11111201, 0x11111202, 0x11121001, 0x11121002, 0x11121100, 0x11121101,
|
||||||
0x010101ffff01ffff, 0x010101ff00000000, 0x010101ff0001ff01, 0x010101ff0101ffff,
|
0x11121102, 0x11121201, 0x12101000, 0x12101200, 0x12101202, 0x12111001, 0x12111100, 0x12111101,
|
||||||
0x010101ff010101ff, 0x01010100ffffffff, 0x01010100ff000001, 0x010101000000ff00,
|
0x12111102, 0x12111201, 0x12121001, 0x12121100, 0x12121101, 0x12121202, 0x10101011, 0x10101012,
|
||||||
0x0101010001010000, 0x0101010100ff0001, 0x010101010001ff01, 0x010101010101ffff,
|
0x10101110, 0x10101111, 0x10101112, 0x10101211, 0x10111010, 0x10111011, 0x10111012, 0x10111110,
|
||||||
|
0x10111111, 0x10111112, 0x10111211, 0x10111212, 0x10121011, 0x10121110, 0x10121111, 0x10121112,
|
||||||
|
0x10121211, 0x11101010, 0x11101011, 0x11101012, 0x11101110, 0x11101111, 0x11101112, 0x11101210,
|
||||||
|
0x11101211, 0x11111010, 0x11111011, 0x11111012, 0x11111110, 0x11111111, 0x11111112, 0x11111210,
|
||||||
|
0x11111211, 0x11111212, 0x11121010, 0x11121011, 0x11121110, 0x11121111, 0x11121112, 0x11121210,
|
||||||
|
0x11121211, 0x11121212, 0x12101011, 0x12101110, 0x12101111, 0x12101211, 0x12101212, 0x12111010,
|
||||||
|
0x12111011, 0x12111110, 0x12111111, 0x12111112, 0x12111210, 0x12111211, 0x12121011, 0x12121110,
|
||||||
|
0x12121111, 0x12121112, 0x12121211, 0x10101020, 0x10101021, 0x10101022, 0x10101120, 0x10101122,
|
||||||
|
0x10101220, 0x10101221, 0x10111021, 0x10111120, 0x10111121, 0x10111220, 0x10111221, 0x10121020,
|
||||||
|
0x10121021, 0x10121022, 0x10121120, 0x10121121, 0x10121122, 0x10121220, 0x10121221, 0x11101021,
|
||||||
|
0x11101121, 0x11101122, 0x11101220, 0x11101221, 0x11101222, 0x11111020, 0x11111021, 0x11111022,
|
||||||
|
0x11111120, 0x11111121, 0x11111122, 0x11111220, 0x11111221, 0x11111222, 0x11121021, 0x11121120,
|
||||||
|
0x11121121, 0x11121221, 0x12101022, 0x12101121, 0x12101122, 0x12101220, 0x12101221, 0x12101222,
|
||||||
|
0x12111021, 0x12111121, 0x12111222, 0x12121022, 0x12121121, 0x12121122, 0x12121220, 0x12121221,
|
||||||
|
0x10102100, 0x10102101, 0x10102102, 0x10102201, 0x10112000, 0x10112101, 0x10112200, 0x10122001,
|
||||||
|
0x10122202, 0x11102101, 0x11102200, 0x11102202, 0x11112001, 0x11112100, 0x11112101, 0x11112102,
|
||||||
|
0x11112200, 0x11112201, 0x11122000, 0x11122002, 0x11122100, 0x11122101, 0x12102002, 0x12102201,
|
||||||
|
0x12112000, 0x12112002, 0x12112101, 0x12112200, 0x12122001, 0x12122201, 0x10102011, 0x10102012,
|
||||||
|
0x10102111, 0x10102212, 0x10112011, 0x10112110, 0x10112111, 0x10112112, 0x10112211, 0x10122111,
|
||||||
|
0x11102011, 0x11102110, 0x11102111, 0x11102112, 0x11102211, 0x11112010, 0x11112011, 0x11112012,
|
||||||
|
0x11112110, 0x11112111, 0x11112112, 0x11112210, 0x11112211, 0x11112212, 0x11122011, 0x11122110,
|
||||||
|
0x11122111, 0x11122112, 0x11122211, 0x12102011, 0x12102111, 0x12102211, 0x12112011, 0x12112110,
|
||||||
|
0x12112111, 0x12112112, 0x12112210, 0x12112211, 0x12122111, 0x10102120, 0x10102220, 0x10112121,
|
||||||
|
0x10112222, 0x10122020, 0x10122121, 0x10122122, 0x10122221, 0x11102121, 0x11102220, 0x11102221,
|
||||||
|
0x11112021, 0x11112121, 0x11112122, 0x11112220, 0x11112221, 0x11122022, 0x11122121, 0x11122220,
|
||||||
|
0x11122222, 0x12102021, 0x12102222, 0x12112022, 0x12112121, 0x12112122, 0x12112220, 0x12112222,
|
||||||
|
0x12122021, 0x10200101, 0x10210100, 0x10210102, 0x10210201, 0x10220101, 0x11200100, 0x11210000,
|
||||||
|
0x11210101, 0x11210102, 0x11210200, 0x11210202, 0x11220001, 0x11220100, 0x11220102, 0x11220201,
|
||||||
|
0x12200001, 0x12210102, 0x12220101, 0x10200011, 0x10200110, 0x10200112, 0x10200211, 0x10210012,
|
||||||
|
0x10210111, 0x10220011, 0x10220012, 0x10220112, 0x10220211, 0x11200111, 0x11200211, 0x11210011,
|
||||||
|
0x11210111, 0x11210112, 0x11210211, 0x11220111, 0x11220112, 0x11220212, 0x12200110, 0x12200212,
|
||||||
|
0x12210012, 0x12210111, 0x12220011, 0x12220112, 0x12220211, 0x10210021, 0x10210122, 0x10210221,
|
||||||
|
0x11200020, 0x11200021, 0x11200122, 0x11210121, 0x11210122, 0x11210220, 0x11220020, 0x12200121,
|
||||||
|
0x12210021, 0x12210122, 0x12220121, 0x10211001, 0x10211002, 0x10211101, 0x10211102, 0x10211202,
|
||||||
|
0x10221001, 0x10221102, 0x10221201, 0x11201000, 0x11201002, 0x11201101, 0x11201200, 0x11201202,
|
||||||
|
0x11211001, 0x11211100, 0x11211101, 0x11211102, 0x11211201, 0x11211202, 0x11221000, 0x11221002,
|
||||||
|
0x11221101, 0x12201100, 0x12201101, 0x12201201, 0x12211000, 0x12211002, 0x12211100, 0x12211101,
|
||||||
|
0x12211102, 0x12211200, 0x12211202, 0x12221001, 0x12221100, 0x12221201, 0x10201111, 0x10201210,
|
||||||
|
0x10201212, 0x10211011, 0x10211111, 0x10211112, 0x10211211, 0x11201110, 0x11201111, 0x11201112,
|
||||||
|
0x11201211, 0x11211010, 0x11211011, 0x11211110, 0x11211111, 0x11211112, 0x11211211, 0x11221011,
|
||||||
|
0x11221110, 0x11221111, 0x11221112, 0x11221211, 0x12201112, 0x12201211, 0x12201212, 0x12211011,
|
||||||
|
0x12211111, 0x12211112, 0x12211211, 0x12211212, 0x12221012, 0x12221111, 0x12221112, 0x12221210,
|
||||||
|
0x10201022, 0x10201221, 0x10211121, 0x10221020, 0x10221122, 0x10221220, 0x10221221, 0x11201020,
|
||||||
|
0x11201121, 0x11201220, 0x11201222, 0x11211021, 0x11211120, 0x11211121, 0x11211122, 0x11211220,
|
||||||
|
0x11211222, 0x11221020, 0x11221121, 0x11221220, 0x12201020, 0x12201022, 0x12201121, 0x12201222,
|
||||||
|
0x12211120, 0x12211122, 0x12211220, 0x12211221, 0x12221020, 0x12221120, 0x12221122, 0x12221222,
|
||||||
|
0x10212102, 0x10212201, 0x10222101, 0x11202001, 0x11212002, 0x11212101, 0x11212202, 0x11222001,
|
||||||
|
0x11222201, 0x12202101, 0x12212001, 0x12212200, 0x12222102, 0x10202011, 0x10202110, 0x10212010,
|
||||||
|
0x10212111, 0x10222011, 0x10222110, 0x10222112, 0x10222211, 0x11202010, 0x11202011, 0x11202111,
|
||||||
|
0x11202112, 0x11202210, 0x11212011, 0x11212110, 0x11212111, 0x11212112, 0x11212211, 0x11222010,
|
||||||
|
0x11222111, 0x11222212, 0x12202012, 0x12202110, 0x12202212, 0x12212111, 0x12222011, 0x12222110,
|
||||||
|
0x12222111, 0x12222211, 0x10212021, 0x10212122, 0x10212220, 0x11202021, 0x11202120, 0x11202221,
|
||||||
|
0x11212020, 0x11212121, 0x11212220, 0x11212222, 0x11222120, 0x11222121, 0x11222221, 0x12202122,
|
||||||
|
0x12212120, 0x12212220, 0x12212222, 0x12222122, 0x20000000, 0x20000002, 0x20000200, 0x20000202,
|
||||||
|
0x20020000, 0x20020002, 0x20020200, 0x20020202, 0x21000101, 0x21010000, 0x21010001, 0x21010100,
|
||||||
|
0x21010102, 0x21010201, 0x21020101, 0x22000000, 0x22000002, 0x22000200, 0x22000202, 0x22010101,
|
||||||
|
0x22020000, 0x22020002, 0x22020200, 0x22020202, 0x20000111, 0x20010011, 0x20010110, 0x20010112,
|
||||||
|
0x20010211, 0x20020111, 0x21000011, 0x21000110, 0x21000211, 0x21010010, 0x21010012, 0x21010111,
|
||||||
|
0x21010112, 0x21010210, 0x21010211, 0x21020110, 0x21020112, 0x21020211, 0x22000111, 0x22000211,
|
||||||
|
0x22010110, 0x22010112, 0x22010211, 0x22020111, 0x20000020, 0x20000022, 0x20000220, 0x20000222,
|
||||||
|
0x20010121, 0x20020020, 0x20020022, 0x20020220, 0x20020222, 0x21010021, 0x21010120, 0x21010221,
|
||||||
|
0x21020121, 0x22000020, 0x22000022, 0x22000220, 0x22000222, 0x22010121, 0x22020020, 0x22020022,
|
||||||
|
0x22020220, 0x22020222, 0x20011100, 0x20011201, 0x21001001, 0x21001100, 0x21011001, 0x21011101,
|
||||||
|
0x21011202, 0x21021001, 0x21021100, 0x21021201, 0x22011100, 0x22011201, 0x20001011, 0x20001211,
|
||||||
|
0x20011012, 0x20011111, 0x20011212, 0x20021112, 0x20021211, 0x21001010, 0x21001011, 0x21001111,
|
||||||
|
0x21001210, 0x21011011, 0x21011110, 0x21011111, 0x21011112, 0x21011211, 0x21011212, 0x21021111,
|
||||||
|
0x21021112, 0x21021210, 0x21021212, 0x22001011, 0x22001110, 0x22001112, 0x22001211, 0x22011010,
|
||||||
|
0x22011012, 0x22011111, 0x22011210, 0x22021112, 0x20011021, 0x20011122, 0x20011221, 0x20021121,
|
||||||
|
0x21001021, 0x21001120, 0x21001221, 0x21001222, 0x21011020, 0x21011121, 0x21011221, 0x21011222,
|
||||||
|
0x21021021, 0x21021122, 0x21021222, 0x22001121, 0x22011021, 0x22011222, 0x22021120, 0x20002000,
|
||||||
|
0x20002002, 0x20002200, 0x20002202, 0x20012101, 0x20022000, 0x20022002, 0x20022200, 0x20022202,
|
||||||
|
0x21002001, 0x21002101, 0x21012001, 0x21012100, 0x21012201, 0x21022101, 0x21022201, 0x22002000,
|
||||||
|
0x22002002, 0x22002200, 0x22002202, 0x22012101, 0x22022000, 0x22022002, 0x22022200, 0x22022202,
|
||||||
|
0x20002111, 0x20002112, 0x20012011, 0x20012110, 0x20012112, 0x20022111, 0x21002011, 0x21002110,
|
||||||
|
0x21002112, 0x21002211, 0x21012010, 0x21012012, 0x21012111, 0x21012212, 0x21022011, 0x21022110,
|
||||||
|
0x22002111, 0x22012112, 0x22012211, 0x22022111, 0x20002020, 0x20002022, 0x20002220, 0x20002222,
|
||||||
|
0x20012121, 0x20022020, 0x20022022, 0x20022220, 0x20022222, 0x21002121, 0x21012021, 0x21012120,
|
||||||
|
0x21012122, 0x22002020, 0x22002022, 0x22002220, 0x22002222, 0x22012121, 0x22022020, 0x22022022,
|
||||||
|
0x22022220, 0x22022222, 0x20100101, 0x20110001, 0x20110102, 0x20110200, 0x20110201, 0x20120101,
|
||||||
|
0x21100001, 0x21100102, 0x21100201, 0x21110101, 0x21110200, 0x21110202, 0x21120201, 0x21120202,
|
||||||
|
0x22100101, 0x22110001, 0x22110100, 0x22110102, 0x22110201, 0x22120101, 0x20100011, 0x20100110,
|
||||||
|
0x20100112, 0x20100211, 0x20110010, 0x20110111, 0x20110210, 0x20110212, 0x20120011, 0x20120110,
|
||||||
|
0x20120112, 0x20120211, 0x21100010, 0x21100111, 0x21110010, 0x21110011, 0x21110110, 0x21110111,
|
||||||
|
0x21110112, 0x21110211, 0x21120012, 0x21120111, 0x22100110, 0x22100112, 0x22110012, 0x22110111,
|
||||||
|
0x22110210, 0x22120011, 0x22120110, 0x22120112, 0x22120211, 0x20100121, 0x20110021, 0x20110120,
|
||||||
|
0x20110221, 0x20120121, 0x21100120, 0x21100122, 0x21100221, 0x21110020, 0x21110022, 0x21110121,
|
||||||
|
0x21110220, 0x21120122, 0x21120221, 0x22100121, 0x22110120, 0x22110122, 0x22120221, 0x20101001,
|
||||||
|
0x20101100, 0x20101102, 0x20111000, 0x20111101, 0x20111200, 0x20121102, 0x21101000, 0x21101202,
|
||||||
|
0x21111001, 0x21111100, 0x21111101, 0x21111102, 0x21111200, 0x21111201, 0x21121000, 0x21121001,
|
||||||
|
0x21121002, 0x21121101, 0x22101100, 0x22101102, 0x22111002, 0x22111100, 0x22111101, 0x22111200,
|
||||||
|
0x22121001, 0x22121201, 0x20101010, 0x20101111, 0x20101210, 0x20101212, 0x20111010, 0x20111011,
|
||||||
|
0x20111110, 0x20111111, 0x20111112, 0x20111211, 0x20121011, 0x20121111, 0x20121211, 0x20121212,
|
||||||
|
0x21101011, 0x21101110, 0x21101111, 0x21101112, 0x21101211, 0x21111010, 0x21111011, 0x21111012,
|
||||||
|
0x21111110, 0x21111111, 0x21111112, 0x21111210, 0x21111211, 0x21111212, 0x21121011, 0x21121110,
|
||||||
|
0x21121111, 0x21121112, 0x21121211, 0x22101011, 0x22101111, 0x22101210, 0x22111011, 0x22111012,
|
||||||
|
0x22111110, 0x22111111, 0x22111112, 0x22111211, 0x22111212, 0x22121010, 0x22121012, 0x22121111,
|
||||||
|
0x22121210, 0x22121212, 0x20101021, 0x20101120, 0x20111020, 0x20111121, 0x20111221, 0x20121020,
|
||||||
|
0x20121122, 0x20121221, 0x21101121, 0x21101220, 0x21101221, 0x21111021, 0x21111022, 0x21111121,
|
||||||
|
0x21111122, 0x21111221, 0x21121121, 0x21121220, 0x22101022, 0x22101120, 0x22101221, 0x22101222,
|
||||||
|
0x22111022, 0x22111120, 0x22111121, 0x22121120, 0x22121122, 0x22121221, 0x20102101, 0x20112102,
|
||||||
|
0x20112201, 0x20122101, 0x21102001, 0x21102102, 0x21112000, 0x21112002, 0x21112101, 0x21112102,
|
||||||
|
0x21112202, 0x21122100, 0x21122101, 0x22102101, 0x22112001, 0x22112102, 0x22112201, 0x22122101,
|
||||||
|
0x20102110, 0x20102112, 0x20102211, 0x20112010, 0x20112012, 0x20112111, 0x20112210, 0x20112212,
|
||||||
|
0x20122010, 0x20122011, 0x20122110, 0x20122112, 0x21102010, 0x21102012, 0x21102111, 0x21102210,
|
||||||
|
0x21102212, 0x21112011, 0x21112110, 0x21112111, 0x21112112, 0x21112211, 0x21122012, 0x21122111,
|
||||||
|
0x21122112, 0x21122212, 0x22102011, 0x22102110, 0x22112010, 0x22112012, 0x22112111, 0x22112212,
|
||||||
|
0x22122011, 0x22122112, 0x20102121, 0x20112121, 0x20122121, 0x21102120, 0x21102122, 0x21102221,
|
||||||
|
0x21112020, 0x21112121, 0x21112220, 0x21122021, 0x22102121, 0x22112021, 0x22112120, 0x22112121,
|
||||||
|
0x22112122, 0x20200000, 0x20200002, 0x20200200, 0x20200202, 0x20210101, 0x20220000, 0x20220002,
|
||||||
|
0x20220200, 0x20220202, 0x21200101, 0x21210001, 0x21210100, 0x21210102, 0x21210201, 0x22200000,
|
||||||
|
0x22200002, 0x22200200, 0x22200202, 0x22210101, 0x22220000, 0x22220002, 0x22220200, 0x22220202,
|
||||||
|
0x20200111, 0x20200211, 0x20210011, 0x20210110, 0x20210112, 0x20210211, 0x20210212, 0x21200112,
|
||||||
|
0x21200211, 0x21210011, 0x21210111, 0x21210210, 0x21210212, 0x21220011, 0x21220110, 0x22200111,
|
||||||
|
0x22210010, 0x22210012, 0x22210112, 0x22210211, 0x20200022, 0x20200220, 0x20200222, 0x20210020,
|
||||||
|
0x20210221, 0x20220022, 0x20220220, 0x20220222, 0x21200121, 0x21210021, 0x21210122, 0x21210221,
|
||||||
|
0x21220121, 0x22200020, 0x22200022, 0x22200220, 0x22200222, 0x22210121, 0x22220020, 0x22220022,
|
||||||
|
0x22220220, 0x22220222, 0x20211201, 0x20221101, 0x21201001, 0x21201100, 0x21211000, 0x21211100,
|
||||||
|
0x21211101, 0x21211200, 0x21211202, 0x21221001, 0x21221101, 0x21221102, 0x21221200, 0x21221201,
|
||||||
|
0x22201101, 0x20201112, 0x20201211, 0x20211010, 0x20211012, 0x20211111, 0x20211210, 0x20221112,
|
||||||
|
0x20221211, 0x21201012, 0x21201111, 0x21211011, 0x21211110, 0x21211111, 0x21211112, 0x21211211,
|
||||||
|
0x21221111, 0x21221212, 0x22201011, 0x22201110, 0x22201111, 0x22201112, 0x22201211, 0x22211012,
|
||||||
|
0x22211111, 0x22211210, 0x20201121, 0x20211021, 0x20211122, 0x20211222, 0x20221021, 0x20221121,
|
||||||
|
0x21201120, 0x21201122, 0x21201222, 0x21211022, 0x21211121, 0x21211122, 0x21211220, 0x21221020,
|
||||||
|
0x21221022, 0x22201122, 0x22211020, 0x22211121, 0x22211122, 0x22211221, 0x22221021, 0x22221120,
|
||||||
|
0x22221122, 0x20202000, 0x20202002, 0x20202200, 0x20202202, 0x20222000, 0x20222002, 0x20222200,
|
||||||
|
0x20222202, 0x21212001, 0x21212100, 0x21212102, 0x21212201, 0x22202000, 0x22202002, 0x22202200,
|
||||||
|
0x22202202, 0x22212101, 0x22222000, 0x22222002, 0x22222200, 0x22222202, 0x20202111, 0x20212110,
|
||||||
|
0x20212211, 0x20222011, 0x20222111, 0x21202011, 0x21212010, 0x21212111, 0x21212212, 0x21222011,
|
||||||
|
0x21222112, 0x21222211, 0x22212010, 0x22212112, 0x20202020, 0x20202022, 0x20202220, 0x20202222,
|
||||||
|
0x20222020, 0x20222022, 0x20222220, 0x20222222, 0x21212021, 0x21212120, 0x21212122, 0x22202020,
|
||||||
|
0x22202022, 0x22202220, 0x22202222, 0x22212121, 0x22222020, 0x22222022, 0x22222220, 0x22222222,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __device__ uint8_t ksigns_iq2xs[128] = {
|
static const __device__ uint8_t ksigns_iq2xs[128] = {
|
||||||
|
|||||||
@@ -166,6 +166,11 @@ torch::Tensor ggml_mul_mat_vec_a8(torch::Tensor W, // quant weight
|
|||||||
(void*)quant_X.data_ptr(),
|
(void*)quant_X.data_ptr(),
|
||||||
(half*)Y.data_ptr(), col, row, stream);
|
(half*)Y.data_ptr(), col, row, stream);
|
||||||
break;
|
break;
|
||||||
|
case 29:
|
||||||
|
mul_mat_vec_iq1_m_q8_1_cuda((void*)W.data_ptr(),
|
||||||
|
(void*)quant_X.data_ptr(),
|
||||||
|
(half*)Y.data_ptr(), col, row, stream);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return Y;
|
return Y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,14 @@ static void mul_mat_vec_iq1_s_q8_1_cuda(const void * vx, const void * vy, half *
|
|||||||
<<<block_nums, block_dims, 0, stream>>>(vx, vy, dst, ncols, nrows);
|
<<<block_nums, block_dims, 0, stream>>>(vx, vy, dst, ncols, nrows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mul_mat_vec_iq1_m_q8_1_cuda(const void * vx, const void * vy, half * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
|
const int block_num_y = (nrows + GGML_CUDA_MMV_Y - 1) / GGML_CUDA_MMV_Y;
|
||||||
|
const dim3 block_nums(block_num_y, 1, 1);
|
||||||
|
const dim3 block_dims(WARP_SIZE, GGML_CUDA_MMV_Y, 1);
|
||||||
|
mul_mat_vec_q<QK_K, QI1_M, block_iq1_m, 1, vec_dot_iq1_m_q8_1>
|
||||||
|
<<<block_nums, block_dims, 0, stream>>>(vx, vy, dst, ncols, nrows);
|
||||||
|
}
|
||||||
|
|
||||||
static void mul_mat_vec_iq4_nl_q8_1_cuda(const void * vx, const void * vy, half * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
static void mul_mat_vec_iq4_nl_q8_1_cuda(const void * vx, const void * vy, half * dst, const int ncols, const int nrows, cudaStream_t stream) {
|
||||||
const int block_num_y = (nrows + GGML_CUDA_MMV_Y - 1) / GGML_CUDA_MMV_Y;
|
const int block_num_y = (nrows + GGML_CUDA_MMV_Y - 1) / GGML_CUDA_MMV_Y;
|
||||||
const dim3 block_nums(block_num_y, 1, 1);
|
const dim3 block_nums(block_num_y, 1, 1);
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
// copied and adapted from https://github.com/ggerganov/llama.cpp/blob/b2899/ggml-cuda/vecdotq.cuh
|
// copied and adapted from https://github.com/ggerganov/llama.cpp/blob/b2899/ggml-cuda/vecdotq.cuh
|
||||||
// and https://github.com/ggerganov/llama.cpp/blob/b2899/ggml-cuda/mmq.cu
|
// and https://github.com/ggerganov/llama.cpp/blob/b2899/ggml-cuda/mmq.cu
|
||||||
|
static __device__ __forceinline__ int get_int_b2(const void * x, const int & i32) {
|
||||||
|
const uint16_t * x16 = (const uint16_t *) x; // assume at least 2 byte alignment
|
||||||
|
|
||||||
|
int x32 = x16[2*i32 + 0] << 0;
|
||||||
|
x32 |= x16[2*i32 + 1] << 16;
|
||||||
|
|
||||||
|
return x32;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __device__ __forceinline__ int get_int_b4(const void * x, const int & i32) {
|
||||||
|
return ((const int *) x)[i32]; // assume at least 4 byte alignment
|
||||||
|
}
|
||||||
|
|
||||||
static __device__ __forceinline__ int get_int_from_int8(const int8_t * x8, const int & i32) {
|
static __device__ __forceinline__ int get_int_from_int8(const int8_t * x8, const int & i32) {
|
||||||
const uint16_t * x16 = (const uint16_t *) (x8 + sizeof(int) * i32); // assume at least 2 byte alignment
|
const uint16_t * x16 = (const uint16_t *) (x8 + sizeof(int) * i32); // assume at least 2 byte alignment
|
||||||
int x32 = 0;
|
int x32 = 0;
|
||||||
@@ -1661,24 +1674,76 @@ static __device__ __forceinline__ float vec_dot_iq1_s_q8_1(
|
|||||||
#if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 610
|
#if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 610
|
||||||
const block_iq1_s * bq1 = (const block_iq1_s *) vbq;
|
const block_iq1_s * bq1 = (const block_iq1_s *) vbq;
|
||||||
|
|
||||||
const int ib32 = iqs;
|
const int qs_packed = get_int_b2(bq1->qs, iqs);
|
||||||
int sumi1 = 0, sumi2 = 0, sumi3 = 0, sumi4 = 0;
|
const uint8_t * qs = (const uint8_t *) &qs_packed;
|
||||||
const uint8_t h1 = bq1->scales[2*ib32+0];
|
|
||||||
const uint8_t h2 = bq1->scales[2*ib32+1];
|
const int qh = bq1->qh[iqs];
|
||||||
const int * q8 = (const int *)bq8_1[ib32].qs;
|
|
||||||
const int * grid1 = (const int *)(iq1s_grid + (bq1->qs[4*ib32+0] | ((h1 & 0x08) << 5)));
|
int sumi = 0;
|
||||||
const int * grid2 = (const int *)(iq1s_grid + (bq1->qs[4*ib32+1] | ((h1 & 0x80) << 1)));
|
#pragma unroll
|
||||||
const int * grid3 = (const int *)(iq1s_grid + (bq1->qs[4*ib32+2] | ((h2 & 0x08) << 5)));
|
for (int l0 = 0; l0 < 8; l0 += 2) {
|
||||||
const int * grid4 = (const int *)(iq1s_grid + (bq1->qs[4*ib32+3] | ((h2 & 0x80) << 1)));
|
const int grid = iq1s_grid_gpu[qs[l0/2] | (((qh >> 3*(l0/2)) & 0x07) << 8)];
|
||||||
for (int j = 0; j < 2; ++j) {
|
|
||||||
sumi1 = __dp4a(q8[j+0], grid1[j], sumi1);
|
const int grid0 = (grid >> 0) & 0x0F0F0F0F;
|
||||||
sumi2 = __dp4a(q8[j+2], grid2[j], sumi2);
|
const int grid1 = (grid >> 4) & 0x0F0F0F0F;
|
||||||
sumi3 = __dp4a(q8[j+4], grid3[j], sumi3);
|
|
||||||
sumi4 = __dp4a(q8[j+6], grid4[j], sumi4);
|
const int u0 = get_int_b4(bq8_1[iqs].qs, l0 + 0);
|
||||||
|
const int u1 = get_int_b4(bq8_1[iqs].qs, l0 + 1);
|
||||||
|
|
||||||
|
sumi = __dp4a(grid0, u0, sumi);
|
||||||
|
sumi = __dp4a(grid1, u1, sumi);
|
||||||
}
|
}
|
||||||
const float d = __half2float(bq1->d) * __low2float(bq8_1[ib32].ds);
|
|
||||||
return d * (sumi1 * (2*(h1 & 7) + 1) + sumi2 * (2*((h1 >> 4) & 7) + 1) +
|
const float d1q = __half2float(bq1->d) * (((qh >> 11) & 0x0E) + 1);
|
||||||
sumi3 * (2*(h2 & 7) + 1) + sumi4 * (2*((h2 >> 4) & 7) + 1));
|
const float delta = -1.0f + IQ1S_DELTA - (qh & 0x8000) * (2.0f*IQ1S_DELTA/0x8000);
|
||||||
|
const float2 ds = __half22float2(bq8_1[iqs].ds);
|
||||||
|
return d1q * (ds.x*sumi + ds.y*delta);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static __device__ __forceinline__ float vec_dot_iq1_m_q8_1(
|
||||||
|
const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & iqs) {
|
||||||
|
#if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 610
|
||||||
|
|
||||||
|
const block_iq1_m * bq1 = (const block_iq1_m *) vbq;
|
||||||
|
|
||||||
|
const int qs_packed = get_int_b4(bq1->qs, iqs);
|
||||||
|
const uint8_t * qs = (const uint8_t *) &qs_packed;
|
||||||
|
|
||||||
|
int sumi[2] = {0};
|
||||||
|
float sumf[2] = {0.0f};
|
||||||
|
#pragma unroll
|
||||||
|
for (int l0 = 0; l0 < 8; l0 += 2) {
|
||||||
|
const int qhl = bq1->qh[2*iqs + l0/4] >> (4 * ((l0/2) % 2));
|
||||||
|
|
||||||
|
const int grid = iq1s_grid_gpu[qs[l0/2] | ((qhl & 0x07) << 8)];
|
||||||
|
|
||||||
|
const int grid0 = (grid >> 0) & 0x0F0F0F0F;
|
||||||
|
const int grid1 = (grid >> 4) & 0x0F0F0F0F;
|
||||||
|
|
||||||
|
const int u0 = get_int_b4(bq8_1[iqs].qs, l0 + 0);
|
||||||
|
const int u1 = get_int_b4(bq8_1[iqs].qs, l0 + 1);
|
||||||
|
|
||||||
|
sumi[l0/4] = __dp4a(grid0, u0, sumi[l0/4]);
|
||||||
|
sumi[l0/4] = __dp4a(grid1, u1, sumi[l0/4]);
|
||||||
|
|
||||||
|
const float delta = -1.0f + IQ1M_DELTA - (qhl & 0x08) * (2.0f*IQ1M_DELTA/0x08);
|
||||||
|
int sumy = 0;
|
||||||
|
sumy = __dp4a(u0, 0x01010101, sumy);
|
||||||
|
sumy = __dp4a(u1, 0x01010101, sumy);
|
||||||
|
sumf[l0/4] += delta*sumy;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t * sc = (const uint16_t *) bq1->scales;
|
||||||
|
|
||||||
|
iq1m_scale_t scale;
|
||||||
|
scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00F0) | ((sc[2] >> 4) & 0x0F00) | (sc[3] & 0xF000);
|
||||||
|
const float d = __half2float(scale.f16) * __low2float(bq8_1[iqs].ds);
|
||||||
|
|
||||||
|
const int tmp = sc[iqs/2] >> (6*(iqs%2));
|
||||||
|
const int sc0 = 2*((tmp >> 0) & 0x07) + 1;
|
||||||
|
const int sc1 = 2*((tmp >> 3) & 0x07) + 1;
|
||||||
|
return d * ((sumi[0] + sumf[0]) * sc0 + (sumi[1] + sumf[1]) * sc1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ TmaMI = MixedInputKernelScheduleType.TmaWarpSpecializedCooperativeMixedInput
|
|||||||
TmaCoop = EpilogueScheduleType.TmaWarpSpecializedCooperative
|
TmaCoop = EpilogueScheduleType.TmaWarpSpecializedCooperative
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass(frozen=True)
|
||||||
class ScheduleConfig:
|
class ScheduleConfig:
|
||||||
tile_shape_mn: Tuple[int, int]
|
tile_shape_mn: Tuple[int, int]
|
||||||
cluster_shape_mnk: Tuple[int, int, int]
|
cluster_shape_mnk: Tuple[int, int, int]
|
||||||
@@ -328,56 +328,137 @@ def generate():
|
|||||||
# about how this works
|
# about how this works
|
||||||
SCRIPT_DIR = os.path.dirname(__file__)
|
SCRIPT_DIR = os.path.dirname(__file__)
|
||||||
|
|
||||||
schedules = [
|
schedule_common_params = dict(
|
||||||
ScheduleConfig(
|
kernel_schedule=TmaMI,
|
||||||
tile_shape_mn=tile_shape_mn,
|
epilogue_schedule=TmaCoop,
|
||||||
cluster_shape_mnk=cluster_shape_mnk,
|
tile_scheduler=TileSchedulerType.StreamK,
|
||||||
kernel_schedule=kernel_schedule,
|
)
|
||||||
epilogue_schedule=epilogue_schedule,
|
|
||||||
tile_scheduler=tile_scheduler,
|
|
||||||
) for tile_shape_mn, cluster_shape_mnk in (
|
|
||||||
((128, 16), (1, 1, 1)),
|
|
||||||
((128, 32), (1, 1, 1)),
|
|
||||||
((128, 64), (1, 1, 1)),
|
|
||||||
((128, 128), (1, 1, 1)),
|
|
||||||
) for kernel_schedule in (TmaMI, ) for epilogue_schedule in (TmaCoop, )
|
|
||||||
for tile_scheduler in (TileSchedulerType.StreamK, )
|
|
||||||
]
|
|
||||||
|
|
||||||
# For now we use the same heuristic for all types
|
# For now we use the same heuristic for all types
|
||||||
|
# Heuristic is currently tuned for H100s
|
||||||
default_heuristic = [
|
default_heuristic = [
|
||||||
("M > 64",
|
#### M = 257+
|
||||||
ScheduleConfig(
|
(
|
||||||
tile_shape_mn=(128, 128),
|
"M > 256 && K <= 16384 && N <= 4096",
|
||||||
cluster_shape_mnk=(1, 1, 1),
|
ScheduleConfig(
|
||||||
kernel_schedule=TmaMI,
|
tile_shape_mn=(128, 128),
|
||||||
epilogue_schedule=TmaCoop,
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
tile_scheduler=TileSchedulerType.StreamK,
|
**schedule_common_params # type: ignore
|
||||||
)),
|
)),
|
||||||
("M > 32",
|
(
|
||||||
ScheduleConfig(
|
"M > 256",
|
||||||
tile_shape_mn=(128, 64),
|
ScheduleConfig(
|
||||||
cluster_shape_mnk=(1, 1, 1),
|
tile_shape_mn=(128, 256),
|
||||||
kernel_schedule=TmaMI,
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
epilogue_schedule=TmaCoop,
|
**schedule_common_params # type: ignore
|
||||||
tile_scheduler=TileSchedulerType.StreamK,
|
)),
|
||||||
)),
|
#### M = 129-256
|
||||||
("M > 16",
|
(
|
||||||
ScheduleConfig(
|
"M > 128 && K <= 4096 && N <= 4096",
|
||||||
tile_shape_mn=(128, 32),
|
ScheduleConfig(
|
||||||
cluster_shape_mnk=(1, 1, 1),
|
tile_shape_mn=(128, 64),
|
||||||
kernel_schedule=TmaMI,
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
epilogue_schedule=TmaCoop,
|
**schedule_common_params # type: ignore
|
||||||
tile_scheduler=TileSchedulerType.StreamK,
|
)),
|
||||||
)),
|
(
|
||||||
(None,
|
"M > 128 && K <= 8192 && N <= 8192",
|
||||||
ScheduleConfig(tile_shape_mn=(128, 16),
|
ScheduleConfig(
|
||||||
cluster_shape_mnk=(1, 1, 1),
|
tile_shape_mn=(128, 128),
|
||||||
kernel_schedule=TmaMI,
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
epilogue_schedule=TmaCoop,
|
**schedule_common_params # type: ignore
|
||||||
tile_scheduler=TileSchedulerType.StreamK))
|
)),
|
||||||
|
(
|
||||||
|
"M > 128",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 256),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
#### M = 65-128
|
||||||
|
(
|
||||||
|
"M > 64 && K <= 4069 && N <= 4069",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 32),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
(
|
||||||
|
"M > 64 && K <= 4069 && N <= 8192",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 64),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
(
|
||||||
|
"M > 64 && K >= 8192 && N >= 12288",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(256, 128),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
(
|
||||||
|
"M > 64",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 128),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
#### M = 33-64
|
||||||
|
(
|
||||||
|
"M > 32 && K <= 6144 && N <= 6144",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 16),
|
||||||
|
cluster_shape_mnk=(1, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
(
|
||||||
|
"M > 32 && K >= 16384 && N >= 12288",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(256, 64),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
(
|
||||||
|
"M > 32",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 64),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
#### M = 17-32
|
||||||
|
(
|
||||||
|
"M > 16 && K <= 12288 && N <= 8192",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 32),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
(
|
||||||
|
"M > 16",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(256, 32),
|
||||||
|
cluster_shape_mnk=(2, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
#### M = 1-16
|
||||||
|
(
|
||||||
|
"N >= 26624",
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(256, 16),
|
||||||
|
cluster_shape_mnk=(1, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
ScheduleConfig(
|
||||||
|
tile_shape_mn=(128, 16),
|
||||||
|
cluster_shape_mnk=(1, 1, 1),
|
||||||
|
**schedule_common_params # type: ignore
|
||||||
|
)),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
schedules = list(set([x[1] for x in default_heuristic]))
|
||||||
|
|
||||||
impl_configs = []
|
impl_configs = []
|
||||||
|
|
||||||
GPTQ_kernel_type_configs = list(
|
GPTQ_kernel_type_configs = list(
|
||||||
|
|||||||
@@ -152,7 +152,8 @@ struct MacheteKernelTemplate {
|
|||||||
|
|
||||||
int M = size<0>(layout_A), N = size<1>(layout_D), K = size<1>(layout_A);
|
int M = size<0>(layout_A), N = size<1>(layout_D), K = size<1>(layout_A);
|
||||||
|
|
||||||
int const group_size = maybe_group_size.value_or(K);
|
int const group_size =
|
||||||
|
maybe_group_size == -1 ? K : maybe_group_size.value_or(K);
|
||||||
int const scale_k = (K + group_size - 1) / group_size;
|
int const scale_k = (K + group_size - 1) / group_size;
|
||||||
|
|
||||||
TORCH_CHECK(size<0>(layout_A) == M && size<1>(layout_A) == K);
|
TORCH_CHECK(size<0>(layout_A) == M && size<1>(layout_A) == K);
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ torch::Tensor run_impl(PyTorchArguments args) {
|
|||||||
auto arguments = MacheteKernel::create_arguments(
|
auto arguments = MacheteKernel::create_arguments(
|
||||||
stream, A_ptr, layout_A, B_ptr, D_ptr, layout_D, C_ptr, layout_C, S_ptr,
|
stream, A_ptr, layout_A, B_ptr, D_ptr, layout_D, C_ptr, layout_C, S_ptr,
|
||||||
layout_S, Z_ptr, layout_Z, args.alpha.value_or(1), args.beta.value_or(0),
|
layout_S, Z_ptr, layout_Z, args.alpha.value_or(1), args.beta.value_or(0),
|
||||||
args.group_size.value_or(K));
|
args.group_size);
|
||||||
TORCH_CHECK(MacheteKernel::can_implement(arguments),
|
TORCH_CHECK(MacheteKernel::can_implement(arguments),
|
||||||
"Machete kernel cannot be run with these arguments");
|
"Machete kernel cannot be run with these arguments");
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ torch::Tensor prepack_impl(torch::Tensor const B) {
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// Allocate output
|
// Allocate output
|
||||||
torch::Tensor D = torch::empty_like(B);
|
torch::Tensor D = torch::empty_like(B, {}, at::MemoryFormat::Contiguous);
|
||||||
|
|
||||||
prepack_B<PrepackedLayoutB>(stream, B_ptr, layout_Bt,
|
prepack_B<PrepackedLayoutB>(stream, B_ptr, layout_Bt,
|
||||||
static_cast<ElementB*>(D.mutable_data_ptr()));
|
static_cast<ElementB*>(D.mutable_data_ptr()));
|
||||||
|
|||||||
1120
csrc/rocm/attention.cu
Normal file
1120
csrc/rocm/attention.cu
Normal file
File diff suppressed because it is too large
Load Diff
14
csrc/rocm/ops.h
Normal file
14
csrc/rocm/ops.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <torch/all.h>
|
||||||
|
|
||||||
|
void paged_attention(torch::Tensor& out, torch::Tensor& exp_sums,
|
||||||
|
torch::Tensor& max_logits, torch::Tensor& tmp_out,
|
||||||
|
torch::Tensor& query, torch::Tensor& key_cache,
|
||||||
|
torch::Tensor& value_cache, int64_t num_kv_heads,
|
||||||
|
double scale, torch::Tensor& block_tables,
|
||||||
|
torch::Tensor& context_lens, int64_t block_size,
|
||||||
|
int64_t max_context_len,
|
||||||
|
const c10::optional<torch::Tensor>& alibi_slopes,
|
||||||
|
const std::string& kv_cache_dtype, double k_scale,
|
||||||
|
double v_scale);
|
||||||
34
csrc/rocm/torch_bindings.cpp
Normal file
34
csrc/rocm/torch_bindings.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "core/registration.h"
|
||||||
|
#include "rocm/ops.h"
|
||||||
|
|
||||||
|
// Note on op signatures:
|
||||||
|
// The X_meta signatures are for the meta functions corresponding to op X.
|
||||||
|
// They must be kept in sync with the signature for X. Generally, only
|
||||||
|
// functions that return Tensors require a meta function.
|
||||||
|
//
|
||||||
|
// See the following links for detailed docs on op registration and function
|
||||||
|
// schemas.
|
||||||
|
// https://docs.google.com/document/d/1_W62p8WJOQQUzPsJYa7s701JXt0qf2OfLub2sbkHOaU/edit#heading=h.ptttacy8y1u9
|
||||||
|
// https://github.com/pytorch/pytorch/blob/main/aten/src/ATen/native/README.md#annotations
|
||||||
|
|
||||||
|
TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, rocm_ops) {
|
||||||
|
// vLLM custom ops for rocm
|
||||||
|
|
||||||
|
// Custom attention op
|
||||||
|
// Compute the attention between an input query and the cached
|
||||||
|
// keys/values using PagedAttention.
|
||||||
|
rocm_ops.def(
|
||||||
|
"paged_attention(Tensor! out, Tensor exp_sums,"
|
||||||
|
" Tensor max_logits, Tensor tmp_out,"
|
||||||
|
" Tensor query, Tensor key_cache,"
|
||||||
|
" Tensor value_cache, int num_kv_heads,"
|
||||||
|
" float scale, Tensor block_tables,"
|
||||||
|
" Tensor context_lens, int block_size,"
|
||||||
|
" int max_context_len,"
|
||||||
|
" Tensor? alibi_slopes,"
|
||||||
|
" str kv_cache_dtype,"
|
||||||
|
" float k_scale, float v_scale) -> ()");
|
||||||
|
rocm_ops.impl("paged_attention", torch::kCUDA, &paged_attention);
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_EXTENSION(TORCH_EXTENSION_NAME)
|
||||||
@@ -74,11 +74,22 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
|
|||||||
|
|
||||||
// prepare_inputs advance_step
|
// prepare_inputs advance_step
|
||||||
ops.def(
|
ops.def(
|
||||||
"advance_step(int num_seqs, int num_queries, int block_size, "
|
"advance_step_flashattn(int num_seqs, int num_queries, int block_size, "
|
||||||
"Tensor! input_tokens, Tensor sampled_token_ids, "
|
"Tensor! input_tokens, Tensor sampled_token_ids, "
|
||||||
"Tensor! input_positions, Tensor! seq_lens, Tensor! slot_mapping, "
|
"Tensor! input_positions, Tensor! seq_lens, Tensor! slot_mapping, "
|
||||||
"Tensor block_tables) -> ()");
|
"Tensor block_tables) -> ()");
|
||||||
ops.impl("advance_step", torch::kCUDA, &advance_step);
|
ops.impl("advance_step_flashattn", torch::kCUDA, &advance_step_flashattn);
|
||||||
|
|
||||||
|
ops.def(
|
||||||
|
"advance_step_flashinfer("
|
||||||
|
" int num_seqs, int num_queries, int block_size,"
|
||||||
|
" Tensor! input_tokens, Tensor sampled_token_ids,"
|
||||||
|
" Tensor! input_positions, Tensor! seq_lens, Tensor! slot_mapping,"
|
||||||
|
" Tensor block_tables, Tensor! paged_kv_indices,"
|
||||||
|
" Tensor! paged_kv_indptr, Tensor! paged_kv_last_page_len,"
|
||||||
|
" Tensor! block_table_bounds"
|
||||||
|
") -> ()");
|
||||||
|
ops.impl("advance_step_flashinfer", torch::kCUDA, &advance_step_flashinfer);
|
||||||
|
|
||||||
// Layernorm
|
// Layernorm
|
||||||
// Apply Root Mean Square (RMS) Normalization to the input tensor.
|
// Apply Root Mean Square (RMS) Normalization to the input tensor.
|
||||||
@@ -181,6 +192,9 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
|
|||||||
"-> Tensor");
|
"-> Tensor");
|
||||||
ops.impl("machete_prepack_B", torch::kCUDA, &machete::prepack_B);
|
ops.impl("machete_prepack_B", torch::kCUDA, &machete::prepack_B);
|
||||||
|
|
||||||
|
ops.def("permute_cols(Tensor A, Tensor perm) -> Tensor");
|
||||||
|
ops.impl("permute_cols", torch::kCUDA, &permute_cols);
|
||||||
|
|
||||||
// gptq_marlin Optimized Quantized GEMM for GPTQ.
|
// gptq_marlin Optimized Quantized GEMM for GPTQ.
|
||||||
ops.def(
|
ops.def(
|
||||||
"gptq_marlin_gemm(Tensor a, Tensor b_q_weight, Tensor b_scales, "
|
"gptq_marlin_gemm(Tensor a, Tensor b_q_weight, Tensor b_scales, "
|
||||||
@@ -261,15 +275,16 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
|
|||||||
"Tensor! A, Tensor! B, Tensor! C,"
|
"Tensor! A, Tensor! B, Tensor! C,"
|
||||||
"Tensor? D_, Tensor? z_, Tensor? delta_bias_,"
|
"Tensor? D_, Tensor? z_, Tensor? delta_bias_,"
|
||||||
"bool delta_softplus,"
|
"bool delta_softplus,"
|
||||||
"Tensor? index_, Tensor(a! -> *)? x) -> Tensor(a)[]");
|
"Tensor? index_, Tensor!? x) -> Tensor[]");
|
||||||
ops.impl("selective_scan_fwd", torch::kCUDA, &selective_scan_fwd);
|
ops.impl("selective_scan_fwd", torch::kCUDA, &selective_scan_fwd);
|
||||||
|
|
||||||
ops.def(
|
ops.def(
|
||||||
"causal_conv1d_update(Tensor! x,"
|
"causal_conv1d_update(Tensor! x,"
|
||||||
"Tensor! conv_state,"
|
"Tensor! conv_state,"
|
||||||
"Tensor! weight,"
|
"Tensor! weight,"
|
||||||
"Tensor? bias_,"
|
"Tensor? bias,"
|
||||||
"bool silu_activation) -> Tensor");
|
"bool silu_activation,"
|
||||||
|
"Tensor? conv_state_indices) -> Tensor");
|
||||||
ops.impl("causal_conv1d_update", torch::kCUDA, &causal_conv1d_update);
|
ops.impl("causal_conv1d_update", torch::kCUDA, &causal_conv1d_update);
|
||||||
|
|
||||||
ops.def(
|
ops.def(
|
||||||
@@ -277,7 +292,7 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
|
|||||||
"Tensor? bias_,"
|
"Tensor? bias_,"
|
||||||
"Tensor? seq_idx_,"
|
"Tensor? seq_idx_,"
|
||||||
"Tensor? initial_states_,"
|
"Tensor? initial_states_,"
|
||||||
"Tensor? final_states_out_,"
|
"Tensor!? final_states_out_,"
|
||||||
"bool silu_activation) -> Tensor");
|
"bool silu_activation) -> Tensor");
|
||||||
ops.impl("causal_conv1d_fwd", torch::kCUDA, &causal_conv1d_fwd);
|
ops.impl("causal_conv1d_fwd", torch::kCUDA, &causal_conv1d_fwd);
|
||||||
#endif
|
#endif
|
||||||
@@ -325,14 +340,14 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
|
|||||||
|
|
||||||
// Compute int8 quantized tensor for given scaling factor.
|
// Compute int8 quantized tensor for given scaling factor.
|
||||||
ops.def(
|
ops.def(
|
||||||
"static_scaled_int8_quant(Tensor! out, Tensor input, Tensor scale) -> "
|
"static_scaled_int8_quant(Tensor! out, Tensor input, Tensor scale,"
|
||||||
"()");
|
"Tensor? azp) -> ()");
|
||||||
ops.impl("static_scaled_int8_quant", torch::kCUDA, &static_scaled_int8_quant);
|
ops.impl("static_scaled_int8_quant", torch::kCUDA, &static_scaled_int8_quant);
|
||||||
|
|
||||||
// Compute int8 quantized tensor and scaling factor
|
// Compute int8 quantized tensor and scaling factor
|
||||||
ops.def(
|
ops.def(
|
||||||
"dynamic_scaled_int8_quant(Tensor! out, Tensor input, Tensor! scale) -> "
|
"dynamic_scaled_int8_quant(Tensor! out, Tensor input, Tensor! scale, "
|
||||||
"()");
|
"Tensor!? azp) -> ()");
|
||||||
ops.impl("dynamic_scaled_int8_quant", torch::kCUDA,
|
ops.impl("dynamic_scaled_int8_quant", torch::kCUDA,
|
||||||
&dynamic_scaled_int8_quant);
|
&dynamic_scaled_int8_quant);
|
||||||
}
|
}
|
||||||
@@ -400,11 +415,6 @@ TORCH_LIBRARY_EXPAND(CONCAT(TORCH_EXTENSION_NAME, _custom_ar), custom_ar) {
|
|||||||
"bool full_nvlink) -> int");
|
"bool full_nvlink) -> int");
|
||||||
custom_ar.impl("init_custom_ar", torch::kCUDA, &init_custom_ar);
|
custom_ar.impl("init_custom_ar", torch::kCUDA, &init_custom_ar);
|
||||||
|
|
||||||
custom_ar.def(
|
|
||||||
"should_custom_ar(Tensor inp, int max_size, int world_size, "
|
|
||||||
"bool full_nvlink) -> bool");
|
|
||||||
custom_ar.impl("should_custom_ar", torch::kCUDA, &should_custom_ar);
|
|
||||||
|
|
||||||
custom_ar.def("all_reduce_reg(int fa, Tensor inp, Tensor! out) -> ()");
|
custom_ar.def("all_reduce_reg(int fa, Tensor inp, Tensor! out) -> ()");
|
||||||
custom_ar.impl("all_reduce_reg", torch::kCUDA, &all_reduce_reg);
|
custom_ar.impl("all_reduce_reg", torch::kCUDA, &all_reduce_reg);
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ Traces can be visualized using https://ui.perfetto.dev/.
|
|||||||
.. tip::
|
.. tip::
|
||||||
|
|
||||||
To stop the profiler - it flushes out all the profile trace files to the directory. This takes time, for example for about 100 requests worth of data for a llama 70b, it takes about 10 minutes to flush out on a H100.
|
To stop the profiler - it flushes out all the profile trace files to the directory. This takes time, for example for about 100 requests worth of data for a llama 70b, it takes about 10 minutes to flush out on a H100.
|
||||||
Set the env variable VLLM_RPC_GET_DATA_TIMEOUT_MS to a big number before you start the server. Say something like 30 minutes.
|
Set the env variable VLLM_RPC_TIMEOUT to a big number before you start the server. Say something like 30 minutes.
|
||||||
``export VLLM_RPC_GET_DATA_TIMEOUT_MS=1800000``
|
``export VLLM_RPC_TIMEOUT=1800000``
|
||||||
|
|
||||||
Example commands and usage:
|
Example commands and usage:
|
||||||
===========================
|
===========================
|
||||||
|
|||||||
@@ -3,15 +3,17 @@
|
|||||||
Installation with ROCm
|
Installation with ROCm
|
||||||
======================
|
======================
|
||||||
|
|
||||||
vLLM supports AMD GPUs with ROCm 6.1.
|
vLLM supports AMD GPUs with ROCm 6.2.
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* OS: Linux
|
* OS: Linux
|
||||||
* Python: 3.8 -- 3.11
|
* Python: 3.9 -- 3.12
|
||||||
* GPU: MI200s (gfx90a), MI300 (gfx942), Radeon RX 7900 series (gfx1100)
|
* GPU: MI200s (gfx90a), MI300 (gfx942), Radeon RX 7900 series (gfx1100)
|
||||||
* ROCm 6.1
|
* ROCm 6.2
|
||||||
|
|
||||||
|
Note: PyTorch 2.5+/ROCm6.2 dropped the support for python 3.8.
|
||||||
|
|
||||||
Installation options:
|
Installation options:
|
||||||
|
|
||||||
@@ -26,8 +28,18 @@ Option 1: Build from source with docker (recommended)
|
|||||||
You can build and install vLLM from source.
|
You can build and install vLLM from source.
|
||||||
|
|
||||||
First, build a docker image from `Dockerfile.rocm <https://github.com/vllm-project/vllm/blob/main/Dockerfile.rocm>`_ and launch a docker container from the image.
|
First, build a docker image from `Dockerfile.rocm <https://github.com/vllm-project/vllm/blob/main/Dockerfile.rocm>`_ and launch a docker container from the image.
|
||||||
|
It is important that the user kicks off the docker build using buildkit. Either the user put DOCKER_BUILDKIT=1 as environment variable when calling docker build command, or the user needs to setup buildkit in the docker daemon configuration /etc/docker/daemon.json as follows and restart the daemon:
|
||||||
|
|
||||||
`Dockerfile.rocm <https://github.com/vllm-project/vllm/blob/main/Dockerfile.rocm>`_ uses ROCm 6.1 by default, but also supports ROCm 5.7 and 6.0 in older vLLM branches.
|
.. code-block:: console
|
||||||
|
|
||||||
|
{
|
||||||
|
"features": {
|
||||||
|
"buildkit": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
`Dockerfile.rocm <https://github.com/vllm-project/vllm/blob/main/Dockerfile.rocm>`_ uses ROCm 6.2 by default, but also supports ROCm 5.7, 6.0 and 6.1 in older vLLM branches.
|
||||||
It provides flexibility to customize the build of docker image using the following arguments:
|
It provides flexibility to customize the build of docker image using the following arguments:
|
||||||
|
|
||||||
* `BASE_IMAGE`: specifies the base image used when running ``docker build``, specifically the PyTorch on ROCm base image.
|
* `BASE_IMAGE`: specifies the base image used when running ``docker build``, specifically the PyTorch on ROCm base image.
|
||||||
@@ -39,13 +51,13 @@ It provides flexibility to customize the build of docker image using the followi
|
|||||||
Their values can be passed in when running ``docker build`` with ``--build-arg`` options.
|
Their values can be passed in when running ``docker build`` with ``--build-arg`` options.
|
||||||
|
|
||||||
|
|
||||||
To build vllm on ROCm 6.1 for MI200 and MI300 series, you can use the default:
|
To build vllm on ROCm 6.2 for MI200 and MI300 series, you can use the default:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ DOCKER_BUILDKIT=1 docker build -f Dockerfile.rocm -t vllm-rocm .
|
$ DOCKER_BUILDKIT=1 docker build -f Dockerfile.rocm -t vllm-rocm .
|
||||||
|
|
||||||
To build vllm on ROCm 6.1 for Radeon RX7900 series (gfx1100), you should specify ``BUILD_FA`` as below:
|
To build vllm on ROCm 6.2 for Radeon RX7900 series (gfx1100), you should specify ``BUILD_FA`` as below:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
@@ -79,37 +91,55 @@ Option 2: Build from source
|
|||||||
|
|
||||||
- `ROCm <https://rocm.docs.amd.com/en/latest/deploy/linux/index.html>`_
|
- `ROCm <https://rocm.docs.amd.com/en/latest/deploy/linux/index.html>`_
|
||||||
- `PyTorch <https://pytorch.org/>`_
|
- `PyTorch <https://pytorch.org/>`_
|
||||||
- `hipBLAS <https://rocm.docs.amd.com/projects/hipBLAS/en/latest/install.html>`_
|
|
||||||
|
|
||||||
For installing PyTorch, you can start from a fresh docker image, e.g, `rocm/pytorch:rocm6.1.2_ubuntu20.04_py3.9_pytorch_staging`, `rocm/pytorch-nightly`.
|
For installing PyTorch, you can start from a fresh docker image, e.g, `rocm/pytorch:rocm6.2_ubuntu20.04_py3.9_pytorch_release_2.3.0`, `rocm/pytorch-nightly`.
|
||||||
|
|
||||||
Alternatively, you can install PyTorch using PyTorch wheels. You can check PyTorch installation guild in PyTorch `Getting Started <https://pytorch.org/get-started/locally/>`_
|
Alternatively, you can install PyTorch using PyTorch wheels. You can check PyTorch installation guide in PyTorch `Getting Started <https://pytorch.org/get-started/locally/>`_
|
||||||
|
|
||||||
|
|
||||||
1. Install `Triton flash attention for ROCm <https://github.com/ROCm/triton>`_
|
1. Install `Triton flash attention for ROCm <https://github.com/ROCm/triton>`_
|
||||||
|
|
||||||
Install ROCm's Triton flash attention (the default triton-mlir branch) following the instructions from `ROCm/triton <https://github.com/ROCm/triton/blob/triton-mlir/README.md>`_
|
Install ROCm's Triton flash attention (the default triton-mlir branch) following the instructions from `ROCm/triton <https://github.com/ROCm/triton/blob/triton-mlir/README.md>`_
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ python3 -m pip install ninja cmake wheel pybind11
|
||||||
|
$ pip uninstall -y triton
|
||||||
|
$ git clone https://github.com/OpenAI/triton.git
|
||||||
|
$ cd triton
|
||||||
|
$ git checkout e192dba
|
||||||
|
$ cd python
|
||||||
|
$ pip3 install .
|
||||||
|
$ cd ../..
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
- If you see HTTP issue related to downloading packages during building triton, please try again as the HTTP error is intermittent.
|
||||||
|
|
||||||
|
|
||||||
2. Optionally, if you choose to use CK flash attention, you can install `flash attention for ROCm <https://github.com/ROCm/flash-attention/tree/ck_tile>`_
|
2. Optionally, if you choose to use CK flash attention, you can install `flash attention for ROCm <https://github.com/ROCm/flash-attention/tree/ck_tile>`_
|
||||||
|
|
||||||
|
|
||||||
Install ROCm's flash attention (v2.5.9.post1) following the instructions from `ROCm/flash-attention <https://github.com/ROCm/flash-attention/tree/ck_tile#amd-gpurocm-support>`_
|
Install ROCm's flash attention (v2.5.9.post1) following the instructions from `ROCm/flash-attention <https://github.com/ROCm/flash-attention/tree/ck_tile#amd-gpurocm-support>`_
|
||||||
Alternatively, wheels intended for vLLM use can be accessed under the releases.
|
Alternatively, wheels intended for vLLM use can be accessed under the releases.
|
||||||
|
|
||||||
|
For example, for ROCm 6.2, suppose your gfx arch is `gfx90a`.
|
||||||
|
Note to get your gfx architecture, run `rocminfo |grep gfx`.
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git clone https://github.com/ROCm/flash-attention.git
|
||||||
|
$ cd flash-attention
|
||||||
|
$ git checkout 3cea2fb
|
||||||
|
$ git submodule update --init
|
||||||
|
$ GPU_ARCHS="gfx90a" python3 setup.py install
|
||||||
|
$ cd ..
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
- You might need to downgrade the "ninja" version to 1.10 it is not used when compiling flash-attention-2 (e.g. `pip install ninja==1.10.2.4`)
|
- You might need to downgrade the "ninja" version to 1.10 it is not used when compiling flash-attention-2 (e.g. `pip install ninja==1.10.2.4`)
|
||||||
|
|
||||||
3. Build vLLM.
|
3. Build vLLM.
|
||||||
|
|
||||||
.. code-block:: console
|
For example, vLLM on ROCM 6.2 can be built with the following steps:
|
||||||
|
|
||||||
$ cd vllm
|
|
||||||
$ pip install -U -r requirements-rocm.txt
|
|
||||||
$ python setup.py develop # This may take 5-10 minutes. Currently, `pip install .`` does not work for ROCm installation
|
|
||||||
|
|
||||||
|
|
||||||
.. tip::
|
|
||||||
|
|
||||||
For example, vLLM v0.5.3 on ROCM 6.1 can be built with the following steps:
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
@@ -117,7 +147,7 @@ Alternatively, wheels intended for vLLM use can be accessed under the releases.
|
|||||||
|
|
||||||
$ # Install PyTorch
|
$ # Install PyTorch
|
||||||
$ pip uninstall torch -y
|
$ pip uninstall torch -y
|
||||||
$ pip install --no-cache-dir --pre torch==2.5.0.dev20240726 --index-url https://download.pytorch.org/whl/nightly/rocm6.1
|
$ pip install --no-cache-dir --pre torch==2.6.0.dev20240918 --index-url https://download.pytorch.org/whl/nightly/rocm6.2
|
||||||
|
|
||||||
$ # Build & install AMD SMI
|
$ # Build & install AMD SMI
|
||||||
$ pip install /opt/rocm/share/amd_smi
|
$ pip install /opt/rocm/share/amd_smi
|
||||||
@@ -127,15 +157,14 @@ Alternatively, wheels intended for vLLM use can be accessed under the releases.
|
|||||||
$ pip install "numpy<2"
|
$ pip install "numpy<2"
|
||||||
$ pip install -r requirements-rocm.txt
|
$ pip install -r requirements-rocm.txt
|
||||||
|
|
||||||
$ # Apply the patch to ROCM 6.1 (requires root permission)
|
|
||||||
$ wget -N https://github.com/ROCm/vllm/raw/fa78403/rocm_patch/libamdhip64.so.6 -P /opt/rocm/lib
|
|
||||||
$ rm -f "$(python3 -c 'import torch; print(torch.__path__[0])')"/lib/libamdhip64.so*
|
|
||||||
|
|
||||||
$ # Build vLLM for MI210/MI250/MI300.
|
$ # Build vLLM for MI210/MI250/MI300.
|
||||||
$ export PYTORCH_ROCM_ARCH="gfx90a;gfx942"
|
$ export PYTORCH_ROCM_ARCH="gfx90a;gfx942"
|
||||||
$ python3 setup.py develop
|
$ python3 setup.py develop
|
||||||
|
|
||||||
|
|
||||||
|
This may take 5-10 minutes. Currently, :code:`pip install .` does not work for ROCm installation.
|
||||||
|
|
||||||
|
|
||||||
.. tip::
|
.. tip::
|
||||||
|
|
||||||
- Triton flash attention is used by default. For benchmarking purposes, it is recommended to run a warm up step before collecting perf numbers.
|
- Triton flash attention is used by default. For benchmarking purposes, it is recommended to run a warm up step before collecting perf numbers.
|
||||||
|
|||||||
@@ -56,9 +56,23 @@ Build from source
|
|||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ pip install --upgrade pip
|
$ pip install --upgrade pip
|
||||||
$ pip install wheel packaging ninja "setuptools>=49.4.0" numpy
|
$ pip install cmake>=3.26 wheel packaging ninja "setuptools-scm>=8" numpy
|
||||||
$ pip install -v -r requirements-cpu.txt --extra-index-url https://download.pytorch.org/whl/cpu
|
$ pip install -v -r requirements-cpu.txt --extra-index-url https://download.pytorch.org/whl/cpu
|
||||||
|
|
||||||
|
- Third, build and install oneDNN library from source:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git clone -b rls-v3.5 https://github.com/oneapi-src/oneDNN.git
|
||||||
|
$ cmake -B ./oneDNN/build -S ./oneDNN -G Ninja -DONEDNN_LIBRARY_TYPE=STATIC \
|
||||||
|
-DONEDNN_BUILD_DOC=OFF \
|
||||||
|
-DONEDNN_BUILD_EXAMPLES=OFF \
|
||||||
|
-DONEDNN_BUILD_TESTS=OFF \
|
||||||
|
-DONEDNN_BUILD_GRAPH=OFF \
|
||||||
|
-DONEDNN_ENABLE_WORKLOAD=INFERENCE \
|
||||||
|
-DONEDNN_ENABLE_PRIMITIVE=MATMUL
|
||||||
|
$ cmake --build ./oneDNN/build --target install --config Release
|
||||||
|
|
||||||
- Finally, build and install vLLM CPU backend:
|
- Finally, build and install vLLM CPU backend:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|||||||
@@ -98,6 +98,13 @@ Here are some common issues that can cause hangs:
|
|||||||
|
|
||||||
If the script runs successfully, you should see the message ``sanity check is successful!``.
|
If the script runs successfully, you should see the message ``sanity check is successful!``.
|
||||||
|
|
||||||
|
Note that multi-node environment is more complicated than single-node. If you see errors such as ``torch.distributed.DistNetworkError``, it is likely that the network/DNS setup is incorrect. In that case, you can manually assign node rank and specify the IP via command line arguments:
|
||||||
|
|
||||||
|
- In the first node, run ``NCCL_DEBUG=TRACE torchrun --nnodes 2 --nproc-per-node=2 --node-rank 0 --master_addr $MASTER_ADDR test.py``.
|
||||||
|
- In the second node, run ``NCCL_DEBUG=TRACE torchrun --nnodes 2 --nproc-per-node=2 --node-rank 1 --master_addr $MASTER_ADDR test.py``.
|
||||||
|
|
||||||
|
Adjust ``--nproc-per-node``, ``--nnodes``, and ``--node-rank`` according to your setup. The difference is that you need to execute different commands (with different ``--node-rank``) on different nodes.
|
||||||
|
|
||||||
If the problem persists, feel free to `open an issue on GitHub <https://github.com/vllm-project/vllm/issues/new/choose>`_, with a detailed description of the issue, your environment, and the logs.
|
If the problem persists, feel free to `open an issue on GitHub <https://github.com/vllm-project/vllm/issues/new/choose>`_, with a detailed description of the issue, your environment, and the logs.
|
||||||
|
|
||||||
Some known issues:
|
Some known issues:
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ You can install vLLM using pip:
|
|||||||
$ # Install vLLM with CUDA 12.1.
|
$ # Install vLLM with CUDA 12.1.
|
||||||
$ pip install vllm
|
$ pip install vllm
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Although we recommend using ``conda`` to create and manage Python environments, it is highly recommended to use ``pip`` to install vLLM. This is because ``pip`` can install ``torch`` with separate library packages like ``NCCL``, while ``conda`` installs ``torch`` with statically linked ``NCCL``. This can cause issues when vLLM tries to use ``NCCL``. See `this issue <https://github.com/vllm-project/vllm/issues/8420>`_ for more details.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
As of now, vLLM's binaries are compiled with CUDA 12.1 and public PyTorch release versions by default.
|
As of now, vLLM's binaries are compiled with CUDA 12.1 and public PyTorch release versions by default.
|
||||||
@@ -34,7 +38,7 @@ You can install vLLM using pip:
|
|||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ # Install vLLM with CUDA 11.8.
|
$ # Install vLLM with CUDA 11.8.
|
||||||
$ export VLLM_VERSION=0.4.0
|
$ export VLLM_VERSION=0.6.1.post1
|
||||||
$ export PYTHON_VERSION=310
|
$ export PYTHON_VERSION=310
|
||||||
$ pip install https://github.com/vllm-project/vllm/releases/download/v${VLLM_VERSION}/vllm-${VLLM_VERSION}+cu118-cp${PYTHON_VERSION}-cp${PYTHON_VERSION}-manylinux1_x86_64.whl --extra-index-url https://download.pytorch.org/whl/cu118
|
$ pip install https://github.com/vllm-project/vllm/releases/download/v${VLLM_VERSION}/vllm-${VLLM_VERSION}+cu118-cp${PYTHON_VERSION}-cp${PYTHON_VERSION}-manylinux1_x86_64.whl --extra-index-url https://download.pytorch.org/whl/cu118
|
||||||
|
|
||||||
@@ -48,7 +52,7 @@ You can install vLLM using pip:
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ export VLLM_VERSION=0.5.4 # vLLM's main branch version is currently set to latest released tag
|
$ export VLLM_VERSION=0.6.1.post1 # vLLM's main branch version is currently set to latest released tag
|
||||||
$ pip install https://vllm-wheels.s3.us-west-2.amazonaws.com/nightly/vllm-${VLLM_VERSION}-cp38-abi3-manylinux1_x86_64.whl
|
$ pip install https://vllm-wheels.s3.us-west-2.amazonaws.com/nightly/vllm-${VLLM_VERSION}-cp38-abi3-manylinux1_x86_64.whl
|
||||||
$ # You can also access a specific commit
|
$ # You can also access a specific commit
|
||||||
$ # export VLLM_COMMIT=...
|
$ # export VLLM_COMMIT=...
|
||||||
@@ -68,6 +72,29 @@ You can also build and install vLLM from source:
|
|||||||
$ cd vllm
|
$ cd vllm
|
||||||
$ pip install -e . # This may take 5-10 minutes.
|
$ pip install -e . # This may take 5-10 minutes.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This will uninstall existing PyTorch, and install the version required by vLLM. If you want to use an existing PyTorch installation, there need to be some changes:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ git clone https://github.com/vllm-project/vllm.git
|
||||||
|
$ cd vllm
|
||||||
|
$ python use_existing_torch.py
|
||||||
|
$ pip install -r requirements-build.txt
|
||||||
|
$ pip install -e . --no-build-isolation
|
||||||
|
|
||||||
|
The differences are:
|
||||||
|
|
||||||
|
- ``python use_existing_torch.py``: This script will remove all the PyTorch versions in the requirements files, so that the existing PyTorch installation will be used.
|
||||||
|
- ``pip install -r requirements-build.txt``: You need to manually install the requirements for building vLLM.
|
||||||
|
- ``pip install -e . --no-build-isolation``: You need to disable build isolation, so that the build system can use the existing PyTorch installation.
|
||||||
|
|
||||||
|
This is especially useful when the PyTorch dependency cannot be easily installed via pip, e.g.:
|
||||||
|
|
||||||
|
- build vLLM with PyTorch nightly or a custom PyTorch build.
|
||||||
|
- build vLLM with aarch64 and cuda (GH200), where the PyTorch wheels are not available on PyPI. Currently, only PyTorch nightly has wheels for aarch64 with CUDA. You can run ``pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu124`` to install PyTorch nightly, and then build vLLM on top of it.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
vLLM can fully run only on Linux, but you can still build it on other systems (for example, macOS). This build is only for development purposes, allowing for imports and a more convenient dev environment. The binaries will not be compiled and not work on non-Linux systems. You can create such a build with the following commands:
|
vLLM can fully run only on Linux, but you can still build it on other systems (for example, macOS). This build is only for development purposes, allowing for imports and a more convenient dev environment. The binaries will not be compiled and not work on non-Linux systems. You can create such a build with the following commands:
|
||||||
@@ -80,17 +107,19 @@ You can also build and install vLLM from source:
|
|||||||
|
|
||||||
.. tip::
|
.. tip::
|
||||||
|
|
||||||
Building from source requires quite a lot compilation. If you are building from source for multiple times, it is beneficial to cache the compilation results. For example, you can install `ccache <https://github.com/ccache/ccache>`_ via either `conda install ccache` or `apt install ccache` . As long as `which ccache` command can find the `ccache` binary, it will be used automatically by the build system. After the first build, the subsequent builds will be much faster.
|
Building from source requires quite a lot compilation. If you are building from source for multiple times, it is beneficial to cache the compilation results. For example, you can install `ccache <https://github.com/ccache/ccache>`_ via either ``conda install ccache`` or ``apt install ccache`` . As long as ``which ccache`` command can find the ``ccache`` binary, it will be used automatically by the build system. After the first build, the subsequent builds will be much faster.
|
||||||
|
|
||||||
.. tip::
|
.. tip::
|
||||||
To avoid your system being overloaded, you can limit the number of compilation jobs
|
To avoid your system being overloaded, you can limit the number of compilation jobs
|
||||||
to be run simultaneously, via the environment variable `MAX_JOBS`. For example:
|
to be run simultaneously, via the environment variable ``MAX_JOBS``. For example:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ export MAX_JOBS=6
|
$ export MAX_JOBS=6
|
||||||
$ pip install -e .
|
$ pip install -e .
|
||||||
|
|
||||||
|
This is especially useful when you are building on less powerful machines. For example, when you use WSL, it only `gives you half of the memory by default <https://learn.microsoft.com/en-us/windows/wsl/wsl-config>`_, and you'd better use ``export MAX_JOBS=1`` to avoid compiling multiple files simultaneously and running out of memory. The side effect is that the build process will be much slower. If you only touch the Python code, slow compilation is okay, as you are building in an editable mode: you can just change the code and run the Python script without any re-compilation or re-installation.
|
||||||
|
|
||||||
.. tip::
|
.. tip::
|
||||||
If you have trouble building vLLM, we recommend using the NVIDIA PyTorch Docker image.
|
If you have trouble building vLLM, we recommend using the NVIDIA PyTorch Docker image.
|
||||||
|
|
||||||
@@ -99,7 +128,7 @@ You can also build and install vLLM from source:
|
|||||||
$ # Use `--ipc=host` to make sure the shared memory is large enough.
|
$ # Use `--ipc=host` to make sure the shared memory is large enough.
|
||||||
$ docker run --gpus all -it --rm --ipc=host nvcr.io/nvidia/pytorch:23.10-py3
|
$ docker run --gpus all -it --rm --ipc=host nvcr.io/nvidia/pytorch:23.10-py3
|
||||||
|
|
||||||
If you don't want to use docker, it is recommended to have a full installation of CUDA Toolkit. You can download and install it from `the official website <https://developer.nvidia.com/cuda-toolkit-archive>`_. After installation, set the environment variable `CUDA_HOME` to the installation path of CUDA Toolkit, and make sure that the `nvcc` compiler is in your `PATH`, e.g.:
|
If you don't want to use docker, it is recommended to have a full installation of CUDA Toolkit. You can download and install it from `the official website <https://developer.nvidia.com/cuda-toolkit-archive>`_. After installation, set the environment variable ``CUDA_HOME`` to the installation path of CUDA Toolkit, and make sure that the ``nvcc`` compiler is in your ``PATH``, e.g.:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
Installation with Neuron
|
Installation with Neuron
|
||||||
========================
|
========================
|
||||||
|
|
||||||
vLLM 0.3.3 onwards supports model inferencing and serving on AWS Trainium/Inferentia with Neuron SDK.
|
vLLM 0.3.3 onwards supports model inferencing and serving on AWS Trainium/Inferentia with Neuron SDK with continuous batching.
|
||||||
At the moment Paged Attention is not supported in Neuron SDK, but naive continuous batching is supported in transformers-neuronx.
|
Paged Attention and Chunked Prefill are currently in development and will be available soon.
|
||||||
Data types currently supported in Neuron SDK are FP16 and BF16.
|
Data types currently supported in Neuron SDK are FP16 and BF16.
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
* OS: Linux
|
* OS: Linux
|
||||||
* Supported Hardware: Intel Data Center GPU (Intel ARC GPU WIP)
|
* Supported Hardware: Intel Data Center GPU, Intel ARC GPU
|
||||||
* OneAPI requirements: oneAPI 2024.1
|
* OneAPI requirements: oneAPI 2024.2
|
||||||
|
|
||||||
.. _xpu_backend_quick_start_dockerfile:
|
.. _xpu_backend_quick_start_dockerfile:
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ Quick start using Dockerfile
|
|||||||
Build from source
|
Build from source
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
- First, install required driver and intel OneAPI 2024.1 or later.
|
- First, install required driver and intel OneAPI 2024.2 or later.
|
||||||
|
|
||||||
- Second, install Python packages for vLLM XPU backend building:
|
- Second, install Python packages for vLLM XPU backend building:
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ vLLM is flexible and easy to use with:
|
|||||||
* Tensor parallelism and pipeline parallelism support for distributed inference
|
* Tensor parallelism and pipeline parallelism support for distributed inference
|
||||||
* Streaming outputs
|
* Streaming outputs
|
||||||
* OpenAI-compatible API server
|
* OpenAI-compatible API server
|
||||||
* Support NVIDIA GPUs, AMD CPUs and GPUs, Intel CPUs and GPUs, PowerPC CPUs, TPU, and AWS Neuron.
|
* Support NVIDIA GPUs, AMD CPUs and GPUs, Intel CPUs and GPUs, PowerPC CPUs, TPU, and AWS Trainium and Inferentia Accelerators.
|
||||||
* Prefix caching support
|
* Prefix caching support
|
||||||
* Multi-lora support
|
* Multi-lora support
|
||||||
|
|
||||||
@@ -107,6 +107,7 @@ Documentation
|
|||||||
quantization/supported_hardware
|
quantization/supported_hardware
|
||||||
quantization/auto_awq
|
quantization/auto_awq
|
||||||
quantization/bnb
|
quantization/bnb
|
||||||
|
quantization/gguf
|
||||||
quantization/int8
|
quantization/int8
|
||||||
quantization/fp8
|
quantization/fp8
|
||||||
quantization/fp8_e5m2_kvcache
|
quantization/fp8_e5m2_kvcache
|
||||||
|
|||||||
@@ -159,3 +159,67 @@ Example request to unload a LoRA adapter:
|
|||||||
-d '{
|
-d '{
|
||||||
"lora_name": "sql_adapter"
|
"lora_name": "sql_adapter"
|
||||||
}'
|
}'
|
||||||
|
|
||||||
|
|
||||||
|
New format for `--lora-modules`
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
In the previous version, users would provide LoRA modules via the following format, either as a key-value pair or in JSON format. For example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
--lora-modules sql-lora=$HOME/.cache/huggingface/hub/models--yard1--llama-2-7b-sql-lora-test/snapshots/0dfa347e8877a4d4ed19ee56c140fa518470028c/
|
||||||
|
|
||||||
|
This would only include the `name` and `path` for each LoRA module, but did not provide a way to specify a `base_model_name`.
|
||||||
|
Now, you can specify a base_model_name alongside the name and path using JSON format. For example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
--lora-modules '{"name": "sql-lora", "path": "/path/to/lora", "base_model_name": "meta-llama/Llama-2-7b"}'
|
||||||
|
|
||||||
|
To provide the backward compatibility support, you can still use the old key-value format (name=path), but the `base_model_name` will remain unspecified in that case.
|
||||||
|
|
||||||
|
|
||||||
|
Lora model lineage in model card
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
The new format of `--lora-modules` is mainly to support the display of parent model information in the model card. Here's an explanation of how your current response supports this:
|
||||||
|
|
||||||
|
- The `parent` field of LoRA model `sql-lora` now links to its base model `meta-llama/Llama-2-7b-hf`. This correctly reflects the hierarchical relationship between the base model and the LoRA adapter.
|
||||||
|
- The `root` field points to the artifact location of the lora adapter.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ curl http://localhost:8000/v1/models
|
||||||
|
|
||||||
|
{
|
||||||
|
"object": "list",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": "meta-llama/Llama-2-7b-hf",
|
||||||
|
"object": "model",
|
||||||
|
"created": 1715644056,
|
||||||
|
"owned_by": "vllm",
|
||||||
|
"root": "~/.cache/huggingface/hub/models--meta-llama--Llama-2-7b-hf/snapshots/01c7f73d771dfac7d292323805ebc428287df4f9/",
|
||||||
|
"parent": null,
|
||||||
|
"permission": [
|
||||||
|
{
|
||||||
|
.....
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sql-lora",
|
||||||
|
"object": "model",
|
||||||
|
"created": 1715644056,
|
||||||
|
"owned_by": "vllm",
|
||||||
|
"root": "~/.cache/huggingface/hub/models--yard1--llama-2-7b-sql-lora-test/snapshots/0dfa347e8877a4d4ed19ee56c140fa518470028c/",
|
||||||
|
"parent": meta-llama/Llama-2-7b-hf,
|
||||||
|
"permission": [
|
||||||
|
{
|
||||||
|
....
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ Decoder-only Language Models
|
|||||||
- MiniCPM
|
- MiniCPM
|
||||||
- :code:`openbmb/MiniCPM-2B-sft-bf16`, :code:`openbmb/MiniCPM-2B-dpo-bf16`, etc.
|
- :code:`openbmb/MiniCPM-2B-sft-bf16`, :code:`openbmb/MiniCPM-2B-dpo-bf16`, etc.
|
||||||
-
|
-
|
||||||
|
* - :code:`MiniCPM3ForCausalLM`
|
||||||
|
- MiniCPM3
|
||||||
|
- :code:`openbmb/MiniCPM3-4B`, etc.
|
||||||
|
-
|
||||||
* - :code:`MistralForCausalLM`
|
* - :code:`MistralForCausalLM`
|
||||||
- Mistral, Mistral-Instruct
|
- Mistral, Mistral-Instruct
|
||||||
- :code:`mistralai/Mistral-7B-v0.1`, :code:`mistralai/Mistral-7B-Instruct-v0.1`, etc.
|
- :code:`mistralai/Mistral-7B-v0.1`, :code:`mistralai/Mistral-7B-Instruct-v0.1`, etc.
|
||||||
@@ -123,6 +127,10 @@ Decoder-only Language Models
|
|||||||
- Nemotron-3, Nemotron-4, Minitron
|
- Nemotron-3, Nemotron-4, Minitron
|
||||||
- :code:`nvidia/Minitron-8B-Base`, :code:`mgoin/Nemotron-4-340B-Base-hf-FP8`, etc.
|
- :code:`nvidia/Minitron-8B-Base`, :code:`mgoin/Nemotron-4-340B-Base-hf-FP8`, etc.
|
||||||
- ✅︎
|
- ✅︎
|
||||||
|
* - :code:`OLMoEForCausalLM`
|
||||||
|
- OLMoE
|
||||||
|
- :code:`allenai/OLMoE-1B-7B-0924`, :code:`allenai/OLMoE-1B-7B-0924-Instruct`, etc.
|
||||||
|
-
|
||||||
* - :code:`OLMoForCausalLM`
|
* - :code:`OLMoForCausalLM`
|
||||||
- OLMo
|
- OLMo
|
||||||
- :code:`allenai/OLMo-1B-hf`, :code:`allenai/OLMo-7B-hf`, etc.
|
- :code:`allenai/OLMo-1B-hf`, :code:`allenai/OLMo-7B-hf`, etc.
|
||||||
@@ -175,6 +183,10 @@ Decoder-only Language Models
|
|||||||
- Starcoder2
|
- Starcoder2
|
||||||
- :code:`bigcode/starcoder2-3b`, :code:`bigcode/starcoder2-7b`, :code:`bigcode/starcoder2-15b`, etc.
|
- :code:`bigcode/starcoder2-3b`, :code:`bigcode/starcoder2-7b`, :code:`bigcode/starcoder2-15b`, etc.
|
||||||
-
|
-
|
||||||
|
* - :code:`SolarForCausalLM`
|
||||||
|
- EXAONE-3
|
||||||
|
- :code:`upstage/solar-pro-preview-instruct`, etc.
|
||||||
|
-
|
||||||
* - :code:`XverseForCausalLM`
|
* - :code:`XverseForCausalLM`
|
||||||
- Xverse
|
- Xverse
|
||||||
- :code:`xverse/XVERSE-7B-Chat`, :code:`xverse/XVERSE-13B-Chat`, :code:`xverse/XVERSE-65B-Chat`, etc.
|
- :code:`xverse/XVERSE-7B-Chat`, :code:`xverse/XVERSE-13B-Chat`, :code:`xverse/XVERSE-65B-Chat`, etc.
|
||||||
@@ -230,13 +242,23 @@ Multimodal Language Models
|
|||||||
* - :code:`LlavaNextVideoForConditionalGeneration`
|
* - :code:`LlavaNextVideoForConditionalGeneration`
|
||||||
- LLaVA-NeXT-Video
|
- LLaVA-NeXT-Video
|
||||||
- Video
|
- Video
|
||||||
- :code:`llava-hf/LLaVA-NeXT-Video-7B-hf`, etc. (see note)
|
- :code:`llava-hf/LLaVA-NeXT-Video-7B-hf`, etc.
|
||||||
|
-
|
||||||
|
* - :code:`LlavaOnevisionForConditionalGeneration`
|
||||||
|
- LLaVA-Onevision
|
||||||
|
- Image\ :sup:`+` / Video
|
||||||
|
- :code:`llava-hf/llava-onevision-qwen2-7b-ov-hf`, :code:`llava-hf/llava-onevision-qwen2-0.5b-ov-hf`, etc.
|
||||||
-
|
-
|
||||||
* - :code:`MiniCPMV`
|
* - :code:`MiniCPMV`
|
||||||
- MiniCPM-V
|
- MiniCPM-V
|
||||||
- Image\ :sup:`+`
|
- Image\ :sup:`+`
|
||||||
- :code:`openbmb/MiniCPM-V-2` (see note), :code:`openbmb/MiniCPM-Llama3-V-2_5`, :code:`openbmb/MiniCPM-V-2_6`, etc.
|
- :code:`openbmb/MiniCPM-V-2` (see note), :code:`openbmb/MiniCPM-Llama3-V-2_5`, :code:`openbmb/MiniCPM-V-2_6`, etc.
|
||||||
-
|
-
|
||||||
|
* - :code:`MllamaForConditionalGeneration`
|
||||||
|
- Llama 3.2
|
||||||
|
- Image
|
||||||
|
- :code:`meta-llama/Llama-3.2-90B-Vision-Instruct`, :code:`meta-llama/Llama-3.2-11B-Vision`, etc.
|
||||||
|
-
|
||||||
* - :code:`PaliGemmaForConditionalGeneration`
|
* - :code:`PaliGemmaForConditionalGeneration`
|
||||||
- PaliGemma
|
- PaliGemma
|
||||||
- Image\ :sup:`E`
|
- Image\ :sup:`E`
|
||||||
@@ -254,7 +276,7 @@ Multimodal Language Models
|
|||||||
-
|
-
|
||||||
* - :code:`QWenLMHeadModel`
|
* - :code:`QWenLMHeadModel`
|
||||||
- Qwen-VL
|
- Qwen-VL
|
||||||
- Image\ :sup:`E`
|
- Image\ :sup:`E+`
|
||||||
- :code:`Qwen/Qwen-VL`, :code:`Qwen/Qwen-VL-Chat`, etc.
|
- :code:`Qwen/Qwen-VL`, :code:`Qwen/Qwen-VL-Chat`, etc.
|
||||||
-
|
-
|
||||||
* - :code:`Qwen2VLForConditionalGeneration`
|
* - :code:`Qwen2VLForConditionalGeneration`
|
||||||
@@ -276,7 +298,7 @@ Multimodal Language Models
|
|||||||
For more details, please see: https://github.com/vllm-project/vllm/pull/4087#issuecomment-2250397630
|
For more details, please see: https://github.com/vllm-project/vllm/pull/4087#issuecomment-2250397630
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
For :code:`LLaVA-NeXT-Video` and :code:`Qwen2-VL`, the latest release of :code:`huggingface/transformers` doesn't work yet, so we need to use a developer version (:code:`21fac7abba2a37fae86106f87fcf9974fd1e3830`) for now.
|
For :code:`Qwen2-VL`, the latest release of :code:`huggingface/transformers` doesn't work yet, so we need to use a developer version (:code:`21fac7abba2a37fae86106f87fcf9974fd1e3830`) for now.
|
||||||
This can be installed by running the following command:
|
This can be installed by running the following command:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@@ -342,7 +364,7 @@ Note that, as an inference engine, vLLM does not introduce new models. Therefore
|
|||||||
|
|
||||||
We have the following levels of testing for models:
|
We have the following levels of testing for models:
|
||||||
|
|
||||||
1. **Strict Consistency**: We compare the output of the model with the output of the model in the HuggingFace Transformers library under greedy decoding. This is the most stringent test. Please refer to `test_models.py <https://github.com/vllm-project/vllm/blob/main/tests/models/test_models.py>`_ and `test_big_models.py <https://github.com/vllm-project/vllm/blob/main/tests/models/test_big_models.py>`_ for the models that have passed this test.
|
1. **Strict Consistency**: We compare the output of the model with the output of the model in the HuggingFace Transformers library under greedy decoding. This is the most stringent test. Please refer to `models tests <https://github.com/vllm-project/vllm/blob/main/tests/models>`_ for the models that have passed this test.
|
||||||
2. **Output Sensibility**: We check if the output of the model is sensible and coherent, by measuring the perplexity of the output and checking for any obvious errors. This is a less stringent test.
|
2. **Output Sensibility**: We check if the output of the model is sensible and coherent, by measuring the perplexity of the output and checking for any obvious errors. This is a less stringent test.
|
||||||
3. **Runtime Functionality**: We check if the model can be loaded and run without errors. This is the least stringent test. Please refer to `functionality tests <https://github.com/vllm-project/vllm/tree/main/tests>`_ and `examples <https://github.com/vllm-project/vllm/tree/main/examples>`_ for the models that have passed this test.
|
3. **Runtime Functionality**: We check if the model can be loaded and run without errors. This is the least stringent test. Please refer to `functionality tests <https://github.com/vllm-project/vllm/tree/main/tests>`_ and `examples <https://github.com/vllm-project/vllm/tree/main/examples>`_ for the models that have passed this test.
|
||||||
4. **Community Feedback**: We rely on the community to provide feedback on the models. If a model is broken or not working as expected, we encourage users to raise issues to report it or open pull requests to fix it. The rest of the models fall under this category.
|
4. **Community Feedback**: We rely on the community to provide feedback on the models. If a model is broken or not working as expected, we encourage users to raise issues to report it or open pull requests to fix it. The rest of the models fall under this category.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Below are the steps to utilize BitsAndBytes with vLLM.
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ pip install bitsandbytes>=0.42.0
|
$ pip install bitsandbytes>=0.44.0
|
||||||
|
|
||||||
vLLM reads the model's config file and supports both in-flight quantization and pre-quantized checkpoint.
|
vLLM reads the model's config file and supports both in-flight quantization and pre-quantized checkpoint.
|
||||||
|
|
||||||
|
|||||||
73
docs/source/quantization/gguf.rst
Normal file
73
docs/source/quantization/gguf.rst
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
.. _gguf:
|
||||||
|
|
||||||
|
GGUF
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Please note that GGUF support in vLLM is highly experimental and under-optimized at the moment, it might be incompatible with other features. Currently, you can use GGUF as a way to reduce memory footprint. If you encounter any issues, please report them to the vLLM team.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Currently, vllm only supports loading single-file GGUF models. If you have a multi-files GGUF model, you can use `gguf-split <https://github.com/ggerganov/llama.cpp/pull/6135>`_ tool to merge them to a single-file model.
|
||||||
|
|
||||||
|
To run a GGUF model with vLLM, you can download and use the local GGUF model from `TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF <https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF>`_ with the following command:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ wget https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf
|
||||||
|
$ # We recommend using the tokenizer from base model to avoid long-time and buggy tokenizer conversion.
|
||||||
|
$ vllm serve ./tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf --tokenizer TinyLlama/TinyLlama-1.1B-Chat-v1.0
|
||||||
|
|
||||||
|
You can also add ``--tensor-parallel-size 2`` to enable tensor parallelism inference with 2 GPUs:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ # We recommend using the tokenizer from base model to avoid long-time and buggy tokenizer conversion.
|
||||||
|
$ vllm serve ./tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf --tokenizer TinyLlama/TinyLlama-1.1B-Chat-v1.0 --tensor-parallel-size 2
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
We recommend using the tokenizer from base model instead of GGUF model. Because the tokenizer conversion from GGUF is time-consuming and unstable, especially for some models with large vocab size.
|
||||||
|
|
||||||
|
You can also use the GGUF model directly through the LLM entrypoint:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from vllm import LLM, SamplingParams
|
||||||
|
|
||||||
|
# In this script, we demonstrate how to pass input to the chat method:
|
||||||
|
conversation = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "You are a helpful assistant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "Hello"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "Hello! How can I assist you today?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "Write an essay about the importance of higher education.",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create a sampling params object.
|
||||||
|
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
|
||||||
|
|
||||||
|
# Create an LLM.
|
||||||
|
llm = LLM(model="./tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf",
|
||||||
|
tokenizer="TinyLlama/TinyLlama-1.1B-Chat-v1.0")
|
||||||
|
# Generate texts from the prompts. The output is a list of RequestOutput objects
|
||||||
|
# that contain the prompt, generated text, and other information.
|
||||||
|
outputs = llm.chat(conversation, sampling_params)
|
||||||
|
|
||||||
|
# Print the outputs.
|
||||||
|
for output in outputs:
|
||||||
|
prompt = output.prompt
|
||||||
|
generated_text = output.outputs[0].text
|
||||||
|
print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")
|
||||||
@@ -79,23 +79,17 @@ def initialize_engine(model: str, quantization: str,
|
|||||||
# It quantizes the model when loading, with some config info from the
|
# It quantizes the model when loading, with some config info from the
|
||||||
# LoRA adapter repo. So need to set the parameter of load_format and
|
# LoRA adapter repo. So need to set the parameter of load_format and
|
||||||
# qlora_adapter_name_or_path as below.
|
# qlora_adapter_name_or_path as below.
|
||||||
engine_args = EngineArgs(
|
engine_args = EngineArgs(model=model,
|
||||||
model=model,
|
quantization=quantization,
|
||||||
quantization=quantization,
|
qlora_adapter_name_or_path=lora_repo,
|
||||||
qlora_adapter_name_or_path=lora_repo,
|
load_format="bitsandbytes",
|
||||||
load_format="bitsandbytes",
|
enable_lora=True,
|
||||||
enable_lora=True,
|
max_lora_rank=64)
|
||||||
max_lora_rank=64,
|
|
||||||
# set it only in GPUs of limited memory
|
|
||||||
enforce_eager=True)
|
|
||||||
else:
|
else:
|
||||||
engine_args = EngineArgs(
|
engine_args = EngineArgs(model=model,
|
||||||
model=model,
|
quantization=quantization,
|
||||||
quantization=quantization,
|
enable_lora=True,
|
||||||
enable_lora=True,
|
max_loras=4)
|
||||||
max_loras=4,
|
|
||||||
# set it only in GPUs of limited memory
|
|
||||||
enforce_eager=True)
|
|
||||||
return LLMEngine.from_engine_args(engine_args)
|
return LLMEngine.from_engine_args(engine_args)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
138
examples/offline_chat_with_tools.py
Normal file
138
examples/offline_chat_with_tools.py
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# ruff: noqa
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
from vllm import LLM
|
||||||
|
from vllm.sampling_params import SamplingParams
|
||||||
|
|
||||||
|
# This script is an offline demo for function calling
|
||||||
|
#
|
||||||
|
# If you want to run a server/client setup, please follow this code:
|
||||||
|
#
|
||||||
|
# - Server:
|
||||||
|
#
|
||||||
|
# ```bash
|
||||||
|
# vllm serve mistralai/Mistral-7B-Instruct-v0.3 --tokenizer-mode mistral --load-format mistral --config-format mistral
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# - Client:
|
||||||
|
#
|
||||||
|
# ```bash
|
||||||
|
# curl --location 'http://<your-node-url>:8000/v1/chat/completions' \
|
||||||
|
# --header 'Content-Type: application/json' \
|
||||||
|
# --header 'Authorization: Bearer token' \
|
||||||
|
# --data '{
|
||||||
|
# "model": "mistralai/Mistral-7B-Instruct-v0.3"
|
||||||
|
# "messages": [
|
||||||
|
# {
|
||||||
|
# "role": "user",
|
||||||
|
# "content": [
|
||||||
|
# {"type" : "text", "text": "Describe this image in detail please."},
|
||||||
|
# {"type": "image_url", "image_url": {"url": "https://s3.amazonaws.com/cms.ipressroom.com/338/files/201808/5b894ee1a138352221103195_A680%7Ejogging-edit/A680%7Ejogging-edit_hero.jpg"}},
|
||||||
|
# {"type" : "text", "text": "and this one as well. Answer in French."},
|
||||||
|
# {"type": "image_url", "image_url": {"url": "https://www.wolframcloud.com/obj/resourcesystem/images/a0e/a0ee3983-46c6-4c92-b85d-059044639928/6af8cfb971db031b.png"}}
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# }'
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# python demo.py simple
|
||||||
|
# python demo.py advanced
|
||||||
|
|
||||||
|
model_name = "mistralai/Mistral-7B-Instruct-v0.3"
|
||||||
|
# or switch to "mistralai/Mistral-Nemo-Instruct-2407"
|
||||||
|
# or "mistralai/Mistral-Large-Instruct-2407"
|
||||||
|
# or any other mistral model with function calling ability
|
||||||
|
|
||||||
|
sampling_params = SamplingParams(max_tokens=8192, temperature=0.0)
|
||||||
|
llm = LLM(model=model_name,
|
||||||
|
tokenizer_mode="mistral",
|
||||||
|
config_format="mistral",
|
||||||
|
load_format="mistral")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_random_id(length=9):
|
||||||
|
characters = string.ascii_letters + string.digits
|
||||||
|
random_id = ''.join(random.choice(characters) for _ in range(length))
|
||||||
|
return random_id
|
||||||
|
|
||||||
|
|
||||||
|
# simulate an API that can be called
|
||||||
|
def get_current_weather(city: str, state: str, unit: 'str'):
|
||||||
|
return (f"The weather in {city}, {state} is 85 degrees {unit}. It is "
|
||||||
|
"partly cloudly, with highs in the 90's.")
|
||||||
|
|
||||||
|
|
||||||
|
tool_funtions = {"get_current_weather": get_current_weather}
|
||||||
|
|
||||||
|
tools = [{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_current_weather",
|
||||||
|
"description": "Get the current weather in a given location",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"city": {
|
||||||
|
"type":
|
||||||
|
"string",
|
||||||
|
"description":
|
||||||
|
"The city to find the weather for, e.g. 'San Francisco'"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"type":
|
||||||
|
"string",
|
||||||
|
"description":
|
||||||
|
"the two-letter abbreviation for the state that the city is"
|
||||||
|
" in, e.g. 'CA' which would mean 'California'"
|
||||||
|
},
|
||||||
|
"unit": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The unit to fetch the temperature in",
|
||||||
|
"enum": ["celsius", "fahrenheit"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["city", "state", "unit"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
messages = [{
|
||||||
|
"role":
|
||||||
|
"user",
|
||||||
|
"content":
|
||||||
|
"Can you tell me what the temperate will be in Dallas, in fahrenheit?"
|
||||||
|
}]
|
||||||
|
|
||||||
|
outputs = llm.chat(messages, sampling_params=sampling_params, tools=tools)
|
||||||
|
output = outputs[0].outputs[0].text.strip()
|
||||||
|
|
||||||
|
# append the assistant message
|
||||||
|
messages.append({
|
||||||
|
"role": "assistant",
|
||||||
|
"content": output,
|
||||||
|
})
|
||||||
|
|
||||||
|
# let's now actually parse and execute the model's output simulating an API call by using the
|
||||||
|
# above defined function
|
||||||
|
tool_calls = json.loads(output)
|
||||||
|
tool_answers = [
|
||||||
|
tool_funtions[call['name']](**call['arguments']) for call in tool_calls
|
||||||
|
]
|
||||||
|
|
||||||
|
# append the answer as a tool message and let the LLM give you an answer
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"content": "\n\n".join(tool_answers),
|
||||||
|
"tool_call_id": generate_random_id(),
|
||||||
|
})
|
||||||
|
|
||||||
|
outputs = llm.chat(messages, sampling_params, tools=tools)
|
||||||
|
|
||||||
|
print(outputs[0].outputs[0].text.strip())
|
||||||
|
# yields
|
||||||
|
# 'The weather in Dallas, TX is 85 degrees fahrenheit. '
|
||||||
|
# 'It is partly cloudly, with highs in the 90's.'
|
||||||
@@ -39,6 +39,33 @@ outputs = llm.chat(conversation,
|
|||||||
use_tqdm=False)
|
use_tqdm=False)
|
||||||
print_outputs(outputs)
|
print_outputs(outputs)
|
||||||
|
|
||||||
|
# You can run batch inference with llm.chat API
|
||||||
|
conversation = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "You are a helpful assistant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "Hello"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "assistant",
|
||||||
|
"content": "Hello! How can I assist you today?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": "Write an essay about the importance of higher education.",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
conversations = [conversation for _ in range(10)]
|
||||||
|
|
||||||
|
# We turn on tqdm progress bar to verify it's indeed running batch inference
|
||||||
|
outputs = llm.chat(messages=conversations,
|
||||||
|
sampling_params=sampling_params,
|
||||||
|
use_tqdm=True)
|
||||||
|
print_outputs(outputs)
|
||||||
|
|
||||||
# A chat template can be optionally supplied.
|
# A chat template can be optionally supplied.
|
||||||
# If not, the model will use its default chat template.
|
# If not, the model will use its default chat template.
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from vllm.sampling_params import SamplingParams
|
|||||||
# - Server:
|
# - Server:
|
||||||
#
|
#
|
||||||
# ```bash
|
# ```bash
|
||||||
# vllm serve mistralai/Pixtral-12B-2409 --tokenizer_mode mistral --limit_mm_per_prompt 'image=4' --max_num_batched_tokens 16384
|
# vllm serve mistralai/Pixtral-12B-2409 --tokenizer-mode mistral --limit-mm-per-prompt 'image=4' --max-model-len 16384
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
# - Client:
|
# - Client:
|
||||||
@@ -45,6 +45,7 @@ def run_simple_demo():
|
|||||||
model_name = "mistralai/Pixtral-12B-2409"
|
model_name = "mistralai/Pixtral-12B-2409"
|
||||||
sampling_params = SamplingParams(max_tokens=8192)
|
sampling_params = SamplingParams(max_tokens=8192)
|
||||||
|
|
||||||
|
# Lower max_num_seqs or max_model_len on low-VRAM GPUs.
|
||||||
llm = LLM(model=model_name, tokenizer_mode="mistral")
|
llm = LLM(model=model_name, tokenizer_mode="mistral")
|
||||||
|
|
||||||
prompt = "Describe this image in one sentence."
|
prompt = "Describe this image in one sentence."
|
||||||
@@ -83,7 +84,7 @@ def run_advanced_demo():
|
|||||||
model=model_name,
|
model=model_name,
|
||||||
tokenizer_mode="mistral",
|
tokenizer_mode="mistral",
|
||||||
limit_mm_per_prompt={"image": max_img_per_msg},
|
limit_mm_per_prompt={"image": max_img_per_msg},
|
||||||
max_num_batched_tokens=max_img_per_msg * max_tokens_per_img,
|
max_model_len=max_img_per_msg * max_tokens_per_img,
|
||||||
)
|
)
|
||||||
|
|
||||||
prompt = "Describe the following image."
|
prompt = "Describe the following image."
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ from vllm.utils import FlexibleArgumentParser
|
|||||||
|
|
||||||
|
|
||||||
# LLaVA-1.5
|
# LLaVA-1.5
|
||||||
def run_llava(question):
|
def run_llava(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
prompt = f"USER: <image>\n{question}\nASSISTANT:"
|
prompt = f"USER: <image>\n{question}\nASSISTANT:"
|
||||||
|
|
||||||
@@ -24,7 +25,8 @@ def run_llava(question):
|
|||||||
|
|
||||||
|
|
||||||
# LLaVA-1.6/LLaVA-NeXT
|
# LLaVA-1.6/LLaVA-NeXT
|
||||||
def run_llava_next(question):
|
def run_llava_next(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
prompt = f"[INST] <image>\n{question} [/INST]"
|
prompt = f"[INST] <image>\n{question} [/INST]"
|
||||||
llm = LLM(model="llava-hf/llava-v1.6-mistral-7b-hf", max_model_len=8192)
|
llm = LLM(model="llava-hf/llava-v1.6-mistral-7b-hf", max_model_len=8192)
|
||||||
@@ -34,15 +36,35 @@ def run_llava_next(question):
|
|||||||
|
|
||||||
# LlaVA-NeXT-Video
|
# LlaVA-NeXT-Video
|
||||||
# Currently only support for video input
|
# Currently only support for video input
|
||||||
def run_llava_next_video(question):
|
def run_llava_next_video(question, modality):
|
||||||
|
assert modality == "video"
|
||||||
|
|
||||||
prompt = f"USER: <video>\n{question} ASSISTANT:"
|
prompt = f"USER: <video>\n{question} ASSISTANT:"
|
||||||
llm = LLM(model="llava-hf/LLaVA-NeXT-Video-7B-hf", max_model_len=8192)
|
llm = LLM(model="llava-hf/LLaVA-NeXT-Video-7B-hf", max_model_len=8192)
|
||||||
stop_token_ids = None
|
stop_token_ids = None
|
||||||
return llm, prompt, stop_token_ids
|
return llm, prompt, stop_token_ids
|
||||||
|
|
||||||
|
|
||||||
|
# LLaVA-OneVision
|
||||||
|
def run_llava_onevision(question, modality):
|
||||||
|
|
||||||
|
if modality == "video":
|
||||||
|
prompt = f"<|im_start|>user <video>\n{question}<|im_end|> \
|
||||||
|
<|im_start|>assistant\n"
|
||||||
|
|
||||||
|
elif modality == "image":
|
||||||
|
prompt = f"<|im_start|>user <image>\n{question}<|im_end|> \
|
||||||
|
<|im_start|>assistant\n"
|
||||||
|
|
||||||
|
llm = LLM(model="llava-hf/llava-onevision-qwen2-7b-ov-hf",
|
||||||
|
max_model_len=32768)
|
||||||
|
stop_token_ids = None
|
||||||
|
return llm, prompt, stop_token_ids
|
||||||
|
|
||||||
|
|
||||||
# Fuyu
|
# Fuyu
|
||||||
def run_fuyu(question):
|
def run_fuyu(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
prompt = f"{question}\n"
|
prompt = f"{question}\n"
|
||||||
llm = LLM(model="adept/fuyu-8b")
|
llm = LLM(model="adept/fuyu-8b")
|
||||||
@@ -51,7 +73,8 @@ def run_fuyu(question):
|
|||||||
|
|
||||||
|
|
||||||
# Phi-3-Vision
|
# Phi-3-Vision
|
||||||
def run_phi3v(question):
|
def run_phi3v(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
prompt = f"<|user|>\n<|image_1|>\n{question}<|end|>\n<|assistant|>\n" # noqa: E501
|
prompt = f"<|user|>\n<|image_1|>\n{question}<|end|>\n<|assistant|>\n" # noqa: E501
|
||||||
# Note: The default setting of max_num_seqs (256) and
|
# Note: The default setting of max_num_seqs (256) and
|
||||||
@@ -60,17 +83,32 @@ def run_phi3v(question):
|
|||||||
|
|
||||||
# In this example, we override max_num_seqs to 5 while
|
# In this example, we override max_num_seqs to 5 while
|
||||||
# keeping the original context length of 128k.
|
# keeping the original context length of 128k.
|
||||||
|
|
||||||
|
# num_crops is an override kwarg to the multimodal image processor;
|
||||||
|
# For some models, e.g., Phi-3.5-vision-instruct, it is recommended
|
||||||
|
# to use 16 for single frame scenarios, and 4 for multi-frame.
|
||||||
|
#
|
||||||
|
# Generally speaking, a larger value for num_crops results in more
|
||||||
|
# tokens per image instance, because it may scale the image more in
|
||||||
|
# the image preprocessing. Some references in the model docs and the
|
||||||
|
# formula for image tokens after the preprocessing
|
||||||
|
# transform can be found below.
|
||||||
|
#
|
||||||
|
# https://huggingface.co/microsoft/Phi-3.5-vision-instruct#loading-the-model-locally
|
||||||
|
# https://huggingface.co/microsoft/Phi-3.5-vision-instruct/blob/main/processing_phi3_v.py#L194
|
||||||
llm = LLM(
|
llm = LLM(
|
||||||
model="microsoft/Phi-3-vision-128k-instruct",
|
model="microsoft/Phi-3-vision-128k-instruct",
|
||||||
trust_remote_code=True,
|
trust_remote_code=True,
|
||||||
max_num_seqs=5,
|
max_num_seqs=5,
|
||||||
|
mm_processor_kwargs={"num_crops": 16},
|
||||||
)
|
)
|
||||||
stop_token_ids = None
|
stop_token_ids = None
|
||||||
return llm, prompt, stop_token_ids
|
return llm, prompt, stop_token_ids
|
||||||
|
|
||||||
|
|
||||||
# PaliGemma
|
# PaliGemma
|
||||||
def run_paligemma(question):
|
def run_paligemma(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
# PaliGemma has special prompt format for VQA
|
# PaliGemma has special prompt format for VQA
|
||||||
prompt = "caption en"
|
prompt = "caption en"
|
||||||
@@ -80,7 +118,8 @@ def run_paligemma(question):
|
|||||||
|
|
||||||
|
|
||||||
# Chameleon
|
# Chameleon
|
||||||
def run_chameleon(question):
|
def run_chameleon(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
prompt = f"{question}<image>"
|
prompt = f"{question}<image>"
|
||||||
llm = LLM(model="facebook/chameleon-7b")
|
llm = LLM(model="facebook/chameleon-7b")
|
||||||
@@ -89,7 +128,8 @@ def run_chameleon(question):
|
|||||||
|
|
||||||
|
|
||||||
# MiniCPM-V
|
# MiniCPM-V
|
||||||
def run_minicpmv(question):
|
def run_minicpmv(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
# 2.0
|
# 2.0
|
||||||
# The official repo doesn't work yet, so we need to use a fork for now
|
# The official repo doesn't work yet, so we need to use a fork for now
|
||||||
@@ -129,7 +169,9 @@ def run_minicpmv(question):
|
|||||||
|
|
||||||
|
|
||||||
# InternVL
|
# InternVL
|
||||||
def run_internvl(question):
|
def run_internvl(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
model_name = "OpenGVLab/InternVL2-2B"
|
model_name = "OpenGVLab/InternVL2-2B"
|
||||||
|
|
||||||
llm = LLM(
|
llm = LLM(
|
||||||
@@ -155,7 +197,8 @@ def run_internvl(question):
|
|||||||
|
|
||||||
|
|
||||||
# BLIP-2
|
# BLIP-2
|
||||||
def run_blip2(question):
|
def run_blip2(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
# BLIP-2 prompt format is inaccurate on HuggingFace model repository.
|
# BLIP-2 prompt format is inaccurate on HuggingFace model repository.
|
||||||
# See https://huggingface.co/Salesforce/blip2-opt-2.7b/discussions/15#64ff02f3f8cf9e4f5b038262 #noqa
|
# See https://huggingface.co/Salesforce/blip2-opt-2.7b/discussions/15#64ff02f3f8cf9e4f5b038262 #noqa
|
||||||
@@ -166,7 +209,8 @@ def run_blip2(question):
|
|||||||
|
|
||||||
|
|
||||||
# Qwen
|
# Qwen
|
||||||
def run_qwen_vl(question):
|
def run_qwen_vl(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
llm = LLM(
|
llm = LLM(
|
||||||
model="Qwen/Qwen-VL",
|
model="Qwen/Qwen-VL",
|
||||||
@@ -180,7 +224,9 @@ def run_qwen_vl(question):
|
|||||||
|
|
||||||
|
|
||||||
# Qwen2-VL
|
# Qwen2-VL
|
||||||
def run_qwen2_vl(question):
|
def run_qwen2_vl(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
model_name = "Qwen/Qwen2-VL-7B-Instruct"
|
model_name = "Qwen/Qwen2-VL-7B-Instruct"
|
||||||
|
|
||||||
llm = LLM(
|
llm = LLM(
|
||||||
@@ -196,10 +242,34 @@ def run_qwen2_vl(question):
|
|||||||
return llm, prompt, stop_token_ids
|
return llm, prompt, stop_token_ids
|
||||||
|
|
||||||
|
|
||||||
|
# LLama
|
||||||
|
def run_mllama(question, modality):
|
||||||
|
assert modality == "image"
|
||||||
|
|
||||||
|
model_name = "meta-llama/Llama-3.2-11B-Vision-Instruct"
|
||||||
|
|
||||||
|
# Note: The default setting of max_num_seqs (256) and
|
||||||
|
# max_model_len (131072) for this model may cause OOM.
|
||||||
|
# You may lower either to run this example on lower-end GPUs.
|
||||||
|
|
||||||
|
# The configuration below has been confirmed to launch on a
|
||||||
|
# single H100 GPU.
|
||||||
|
llm = LLM(
|
||||||
|
model=model_name,
|
||||||
|
max_num_seqs=16,
|
||||||
|
enforce_eager=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
prompt = f"<|image|><|begin_of_text|>{question}"
|
||||||
|
stop_token_ids = None
|
||||||
|
return llm, prompt, stop_token_ids
|
||||||
|
|
||||||
|
|
||||||
model_example_map = {
|
model_example_map = {
|
||||||
"llava": run_llava,
|
"llava": run_llava,
|
||||||
"llava-next": run_llava_next,
|
"llava-next": run_llava_next,
|
||||||
"llava-next-video": run_llava_next_video,
|
"llava-next-video": run_llava_next_video,
|
||||||
|
"llava-onevision": run_llava_onevision,
|
||||||
"fuyu": run_fuyu,
|
"fuyu": run_fuyu,
|
||||||
"phi3_v": run_phi3v,
|
"phi3_v": run_phi3v,
|
||||||
"paligemma": run_paligemma,
|
"paligemma": run_paligemma,
|
||||||
@@ -209,6 +279,7 @@ model_example_map = {
|
|||||||
"internvl_chat": run_internvl,
|
"internvl_chat": run_internvl,
|
||||||
"qwen_vl": run_qwen_vl,
|
"qwen_vl": run_qwen_vl,
|
||||||
"qwen2_vl": run_qwen2_vl,
|
"qwen2_vl": run_qwen2_vl,
|
||||||
|
"mllama": run_mllama,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -255,7 +326,7 @@ def main(args):
|
|||||||
data = mm_input["data"]
|
data = mm_input["data"]
|
||||||
question = mm_input["question"]
|
question = mm_input["question"]
|
||||||
|
|
||||||
llm, prompt, stop_token_ids = model_example_map[model](question)
|
llm, prompt, stop_token_ids = model_example_map[model](question, modality)
|
||||||
|
|
||||||
# We set temperature to 0.2 so that outputs can be different
|
# We set temperature to 0.2 so that outputs can be different
|
||||||
# even when all prompts are identical when running batch inference.
|
# even when all prompts are identical when running batch inference.
|
||||||
@@ -306,6 +377,7 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument('--modality',
|
parser.add_argument('--modality',
|
||||||
type=str,
|
type=str,
|
||||||
default="image",
|
default="image",
|
||||||
|
choices=['image', 'video'],
|
||||||
help='Modality of the input.')
|
help='Modality of the input.')
|
||||||
parser.add_argument('--num-frames',
|
parser.add_argument('--num-frames',
|
||||||
type=int,
|
type=int,
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ multi-image input on vision language models, using the chat template defined
|
|||||||
by the model.
|
by the model.
|
||||||
"""
|
"""
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from typing import List
|
from typing import List, NamedTuple, Optional
|
||||||
|
|
||||||
|
from PIL.Image import Image
|
||||||
from transformers import AutoProcessor, AutoTokenizer
|
from transformers import AutoProcessor, AutoTokenizer
|
||||||
|
|
||||||
from vllm import LLM, SamplingParams
|
from vllm import LLM, SamplingParams
|
||||||
@@ -19,21 +20,87 @@ IMAGE_URLS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def load_phi3v(question, image_urls: List[str]):
|
class ModelRequestData(NamedTuple):
|
||||||
|
llm: LLM
|
||||||
|
prompt: str
|
||||||
|
stop_token_ids: Optional[List[str]]
|
||||||
|
image_data: List[Image]
|
||||||
|
chat_template: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
def load_qwenvl_chat(question: str, image_urls: List[str]) -> ModelRequestData:
|
||||||
|
model_name = "Qwen/Qwen-VL-Chat"
|
||||||
|
llm = LLM(
|
||||||
|
model=model_name,
|
||||||
|
trust_remote_code=True,
|
||||||
|
max_num_seqs=5,
|
||||||
|
limit_mm_per_prompt={"image": len(image_urls)},
|
||||||
|
)
|
||||||
|
placeholders = "".join(f"Picture {i}: <img></img>\n"
|
||||||
|
for i, _ in enumerate(image_urls, start=1))
|
||||||
|
|
||||||
|
# This model does not have a chat_template attribute on its tokenizer,
|
||||||
|
# so we need to explicitly pass it. We use ChatML since it's used in the
|
||||||
|
# generation utils of the model:
|
||||||
|
# https://huggingface.co/Qwen/Qwen-VL-Chat/blob/main/qwen_generation_utils.py#L265
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained(model_name,
|
||||||
|
trust_remote_code=True)
|
||||||
|
|
||||||
|
# Copied from: https://huggingface.co/docs/transformers/main/en/chat_templating
|
||||||
|
chat_template = "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}" # noqa: E501
|
||||||
|
|
||||||
|
messages = [{'role': 'user', 'content': f"{placeholders}\n{question}"}]
|
||||||
|
prompt = tokenizer.apply_chat_template(messages,
|
||||||
|
tokenize=False,
|
||||||
|
add_generation_prompt=True,
|
||||||
|
chat_template=chat_template)
|
||||||
|
|
||||||
|
stop_tokens = ["<|endoftext|>", "<|im_start|>", "<|im_end|>"]
|
||||||
|
stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]
|
||||||
|
return ModelRequestData(
|
||||||
|
llm=llm,
|
||||||
|
prompt=prompt,
|
||||||
|
stop_token_ids=stop_token_ids,
|
||||||
|
image_data=[fetch_image(url) for url in image_urls],
|
||||||
|
chat_template=chat_template,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def load_phi3v(question: str, image_urls: List[str]) -> ModelRequestData:
|
||||||
|
# num_crops is an override kwarg to the multimodal image processor;
|
||||||
|
# For some models, e.g., Phi-3.5-vision-instruct, it is recommended
|
||||||
|
# to use 16 for single frame scenarios, and 4 for multi-frame.
|
||||||
|
#
|
||||||
|
# Generally speaking, a larger value for num_crops results in more
|
||||||
|
# tokens per image instance, because it may scale the image more in
|
||||||
|
# the image preprocessing. Some references in the model docs and the
|
||||||
|
# formula for image tokens after the preprocessing
|
||||||
|
# transform can be found below.
|
||||||
|
#
|
||||||
|
# https://huggingface.co/microsoft/Phi-3.5-vision-instruct#loading-the-model-locally
|
||||||
|
# https://huggingface.co/microsoft/Phi-3.5-vision-instruct/blob/main/processing_phi3_v.py#L194
|
||||||
llm = LLM(
|
llm = LLM(
|
||||||
model="microsoft/Phi-3.5-vision-instruct",
|
model="microsoft/Phi-3.5-vision-instruct",
|
||||||
trust_remote_code=True,
|
trust_remote_code=True,
|
||||||
max_model_len=4096,
|
max_model_len=4096,
|
||||||
limit_mm_per_prompt={"image": len(image_urls)},
|
limit_mm_per_prompt={"image": len(image_urls)},
|
||||||
|
mm_processor_kwargs={"num_crops": 4},
|
||||||
)
|
)
|
||||||
placeholders = "\n".join(f"<|image_{i}|>"
|
placeholders = "\n".join(f"<|image_{i}|>"
|
||||||
for i, _ in enumerate(image_urls, start=1))
|
for i, _ in enumerate(image_urls, start=1))
|
||||||
prompt = f"<|user|>\n{placeholders}\n{question}<|end|>\n<|assistant|>\n"
|
prompt = f"<|user|>\n{placeholders}\n{question}<|end|>\n<|assistant|>\n"
|
||||||
stop_token_ids = None
|
stop_token_ids = None
|
||||||
return llm, prompt, stop_token_ids, None
|
|
||||||
|
return ModelRequestData(
|
||||||
|
llm=llm,
|
||||||
|
prompt=prompt,
|
||||||
|
stop_token_ids=stop_token_ids,
|
||||||
|
image_data=[fetch_image(url) for url in image_urls],
|
||||||
|
chat_template=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def load_internvl(question, image_urls: List[str]):
|
def load_internvl(question: str, image_urls: List[str]) -> ModelRequestData:
|
||||||
model_name = "OpenGVLab/InternVL2-2B"
|
model_name = "OpenGVLab/InternVL2-2B"
|
||||||
|
|
||||||
llm = LLM(
|
llm = LLM(
|
||||||
@@ -61,10 +128,16 @@ def load_internvl(question, image_urls: List[str]):
|
|||||||
stop_tokens = ["<|endoftext|>", "<|im_start|>", "<|im_end|>", "<|end|>"]
|
stop_tokens = ["<|endoftext|>", "<|im_start|>", "<|im_end|>", "<|end|>"]
|
||||||
stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]
|
stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]
|
||||||
|
|
||||||
return llm, prompt, stop_token_ids, None
|
return ModelRequestData(
|
||||||
|
llm=llm,
|
||||||
|
prompt=prompt,
|
||||||
|
stop_token_ids=stop_token_ids,
|
||||||
|
image_data=[fetch_image(url) for url in image_urls],
|
||||||
|
chat_template=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def load_qwen2_vl(question, image_urls: List[str]):
|
def load_qwen2_vl(question, image_urls: List[str]) -> ModelRequestData:
|
||||||
try:
|
try:
|
||||||
from qwen_vl_utils import process_vision_info
|
from qwen_vl_utils import process_vision_info
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
@@ -111,31 +184,35 @@ def load_qwen2_vl(question, image_urls: List[str]):
|
|||||||
else:
|
else:
|
||||||
image_data, _ = process_vision_info(messages)
|
image_data, _ = process_vision_info(messages)
|
||||||
|
|
||||||
return llm, prompt, stop_token_ids, image_data
|
return ModelRequestData(
|
||||||
|
llm=llm,
|
||||||
|
prompt=prompt,
|
||||||
|
stop_token_ids=stop_token_ids,
|
||||||
|
image_data=image_data,
|
||||||
|
chat_template=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
model_example_map = {
|
model_example_map = {
|
||||||
"phi3_v": load_phi3v,
|
"phi3_v": load_phi3v,
|
||||||
"internvl_chat": load_internvl,
|
"internvl_chat": load_internvl,
|
||||||
"qwen2_vl": load_qwen2_vl,
|
"qwen2_vl": load_qwen2_vl,
|
||||||
|
"qwen_vl_chat": load_qwenvl_chat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def run_generate(model, question: str, image_urls: List[str]):
|
def run_generate(model, question: str, image_urls: List[str]):
|
||||||
llm, prompt, stop_token_ids, image_data = model_example_map[model](
|
req_data = model_example_map[model](question, image_urls)
|
||||||
question, image_urls)
|
|
||||||
if image_data is None:
|
|
||||||
image_data = [fetch_image(url) for url in image_urls]
|
|
||||||
|
|
||||||
sampling_params = SamplingParams(temperature=0.0,
|
sampling_params = SamplingParams(temperature=0.0,
|
||||||
max_tokens=128,
|
max_tokens=128,
|
||||||
stop_token_ids=stop_token_ids)
|
stop_token_ids=req_data.stop_token_ids)
|
||||||
|
|
||||||
outputs = llm.generate(
|
outputs = req_data.llm.generate(
|
||||||
{
|
{
|
||||||
"prompt": prompt,
|
"prompt": req_data.prompt,
|
||||||
"multi_modal_data": {
|
"multi_modal_data": {
|
||||||
"image": image_data
|
"image": req_data.image_data
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sampling_params=sampling_params)
|
sampling_params=sampling_params)
|
||||||
@@ -146,29 +223,31 @@ def run_generate(model, question: str, image_urls: List[str]):
|
|||||||
|
|
||||||
|
|
||||||
def run_chat(model: str, question: str, image_urls: List[str]):
|
def run_chat(model: str, question: str, image_urls: List[str]):
|
||||||
llm, _, stop_token_ids, _ = model_example_map[model](question, image_urls)
|
req_data = model_example_map[model](question, image_urls)
|
||||||
|
|
||||||
sampling_params = SamplingParams(temperature=0.0,
|
sampling_params = SamplingParams(temperature=0.0,
|
||||||
max_tokens=128,
|
max_tokens=128,
|
||||||
stop_token_ids=stop_token_ids)
|
stop_token_ids=req_data.stop_token_ids)
|
||||||
|
outputs = req_data.llm.chat(
|
||||||
outputs = llm.chat([{
|
[{
|
||||||
"role":
|
"role":
|
||||||
"user",
|
"user",
|
||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"text": question,
|
"text": question,
|
||||||
},
|
|
||||||
*({
|
|
||||||
"type": "image_url",
|
|
||||||
"image_url": {
|
|
||||||
"url": image_url
|
|
||||||
},
|
},
|
||||||
} for image_url in image_urls),
|
*({
|
||||||
],
|
"type": "image_url",
|
||||||
}],
|
"image_url": {
|
||||||
sampling_params=sampling_params)
|
"url": image_url
|
||||||
|
},
|
||||||
|
} for image_url in image_urls),
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
sampling_params=sampling_params,
|
||||||
|
chat_template=req_data.chat_template,
|
||||||
|
)
|
||||||
|
|
||||||
for o in outputs:
|
for o in outputs:
|
||||||
generated_text = o.outputs[0].text
|
generated_text = o.outputs[0].text
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ prompts = [
|
|||||||
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
|
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
|
||||||
|
|
||||||
# Create an LLM.
|
# Create an LLM.
|
||||||
llm = LLM(model="facebook/opt-125m")
|
llm = LLM(model="facebook/opt-125m", tensor_parallel_size=1)
|
||||||
|
|
||||||
llm.start_profile()
|
llm.start_profile()
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ chat_completion_from_url = client.chat.completions.create(
|
|||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"text": "What’s in this image?"
|
"text": "What's in this image?"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "image_url",
|
"type": "image_url",
|
||||||
@@ -75,7 +75,7 @@ chat_completion_from_base64 = client.chat.completions.create(
|
|||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"text": "What’s in this image?"
|
"text": "What's in this image?"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "image_url",
|
"type": "image_url",
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ echo 'vLLM codespell: Done'
|
|||||||
|
|
||||||
# Lint specified files
|
# Lint specified files
|
||||||
lint() {
|
lint() {
|
||||||
ruff "$@"
|
ruff check "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Lint files that differ from main branch. Ignores dirs that are not slated
|
# Lint files that differ from main branch. Ignores dirs that are not slated
|
||||||
@@ -175,7 +175,7 @@ lint_changed() {
|
|||||||
|
|
||||||
if ! git diff --diff-filter=ACM --quiet --exit-code "$MERGEBASE" -- '*.py' '*.pyi' &>/dev/null; then
|
if ! git diff --diff-filter=ACM --quiet --exit-code "$MERGEBASE" -- '*.py' '*.pyi' &>/dev/null; then
|
||||||
git diff --name-only --diff-filter=ACM "$MERGEBASE" -- '*.py' '*.pyi' | xargs \
|
git diff --name-only --diff-filter=ACM "$MERGEBASE" -- '*.py' '*.pyi' | xargs \
|
||||||
ruff
|
ruff check
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ requires = [
|
|||||||
"cmake>=3.26",
|
"cmake>=3.26",
|
||||||
"ninja",
|
"ninja",
|
||||||
"packaging",
|
"packaging",
|
||||||
"setuptools >= 49.4.0",
|
"setuptools>=61",
|
||||||
|
"setuptools-scm>=8.0",
|
||||||
"torch == 2.4.0",
|
"torch == 2.4.0",
|
||||||
"wheel",
|
"wheel",
|
||||||
"jinja2",
|
"jinja2",
|
||||||
@@ -19,6 +20,10 @@ exclude = [
|
|||||||
"examples/fp8/quantizer/quantize.py"
|
"examples/fp8/quantizer/quantize.py"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"vllm/version.py" = ["F401"]
|
||||||
|
"vllm/_version.py" = ["ALL"]
|
||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
select = [
|
select = [
|
||||||
# pycodestyle
|
# pycodestyle
|
||||||
@@ -42,6 +47,8 @@ ignore = [
|
|||||||
"E731",
|
"E731",
|
||||||
# Loop control variable not used within loop body
|
# Loop control variable not used within loop body
|
||||||
"B007",
|
"B007",
|
||||||
|
# f-string format
|
||||||
|
"UP032",
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
@@ -76,7 +83,7 @@ exclude = [
|
|||||||
|
|
||||||
[tool.codespell]
|
[tool.codespell]
|
||||||
ignore-words-list = "dout, te, indicies, subtile"
|
ignore-words-list = "dout, te, indicies, subtile"
|
||||||
skip = "./tests/prompts,./benchmarks/sonnet.txt,./tests/lora/data,./build"
|
skip = "./tests/models/fixtures,./tests/prompts,./benchmarks/sonnet.txt,./tests/lora/data,./build"
|
||||||
|
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
use_parentheses = true
|
use_parentheses = true
|
||||||
@@ -85,5 +92,6 @@ skip_gitignore = true
|
|||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
markers = [
|
markers = [
|
||||||
"skip_global_cleanup",
|
"skip_global_cleanup",
|
||||||
"vlm: run tests for vision language models only",
|
"core_model: run this model test in each PR instead of just daily",
|
||||||
|
"distributed_2_gpus: run this test only in distributed tests for 2 GPUs",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
cmake>=3.26
|
cmake>=3.26
|
||||||
ninja
|
ninja
|
||||||
packaging
|
packaging
|
||||||
setuptools>=49.4.0
|
setuptools>=61
|
||||||
|
setuptools-scm>=8
|
||||||
torch==2.4.0
|
torch==2.4.0
|
||||||
wheel
|
wheel
|
||||||
jinja2
|
jinja2
|
||||||
|
|||||||
@@ -4,28 +4,30 @@ numpy < 2.0.0
|
|||||||
requests
|
requests
|
||||||
tqdm
|
tqdm
|
||||||
py-cpuinfo
|
py-cpuinfo
|
||||||
transformers >= 4.43.2 # Required for Chameleon and Llama 3.1 hotfox.
|
transformers >= 4.45.0 # Required for Llama 3.2.
|
||||||
tokenizers >= 0.19.1 # Required for Llama 3.
|
tokenizers >= 0.19.1 # Required for Llama 3.
|
||||||
protobuf # Required by LlamaTokenizer.
|
protobuf # Required by LlamaTokenizer.
|
||||||
fastapi
|
fastapi < 0.113.0; python_version < '3.9'
|
||||||
|
fastapi >= 0.114.1; python_version >= '3.9'
|
||||||
aiohttp
|
aiohttp
|
||||||
openai >= 1.40.0 # Ensure modern openai package (ensure types module present)
|
openai >= 1.40.0 # Ensure modern openai package (ensure types module present)
|
||||||
uvicorn[standard]
|
uvicorn[standard]
|
||||||
pydantic >= 2.8 # Required for OpenAI server.
|
pydantic >= 2.9 # Required for fastapi >= 0.113.0
|
||||||
pillow # Required for image processing
|
pillow # Required for image processing
|
||||||
prometheus_client >= 0.18.0
|
prometheus_client >= 0.18.0
|
||||||
prometheus-fastapi-instrumentator >= 7.0.0
|
prometheus-fastapi-instrumentator >= 7.0.0
|
||||||
tiktoken >= 0.6.0 # Required for DBRX tokenizer
|
tiktoken >= 0.6.0 # Required for DBRX tokenizer
|
||||||
lm-format-enforcer == 0.10.6
|
lm-format-enforcer == 0.10.6
|
||||||
outlines >= 0.0.43, < 0.1 # Requires torch >= 2.1.0
|
outlines >= 0.0.43, < 0.1
|
||||||
typing_extensions >= 4.10
|
typing_extensions >= 4.10
|
||||||
filelock >= 3.10.4 # filelock starts to support `mode` argument from 3.10.4
|
filelock >= 3.10.4 # filelock starts to support `mode` argument from 3.10.4
|
||||||
partial-json-parser # used for parsing partial JSON outputs
|
partial-json-parser # used for parsing partial JSON outputs
|
||||||
pyzmq
|
pyzmq
|
||||||
msgspec
|
msgspec
|
||||||
gguf == 0.9.1
|
gguf == 0.10.0
|
||||||
importlib_metadata
|
importlib_metadata
|
||||||
mistral_common >= 1.4.0
|
mistral_common >= 1.4.3
|
||||||
pyyaml
|
pyyaml
|
||||||
six>=1.16.0; python_version > '3.11' # transitive dependency of pandas that needs to be the latest version for python 3.12
|
six>=1.16.0; python_version > '3.11' # transitive dependency of pandas that needs to be the latest version for python 3.12
|
||||||
|
setuptools>=74.1.1; python_version > '3.11' # Setuptools is used by triton, we need to ensure a modern version is installed for 3.12+ so that it does not try to import distutils, which was removed in 3.12
|
||||||
einops # Required for Qwen2-VL.
|
einops # Required for Qwen2-VL.
|
||||||
|
|||||||
@@ -8,4 +8,3 @@ torch == 2.4.0
|
|||||||
# These must be updated alongside torch
|
# These must be updated alongside torch
|
||||||
torchvision == 0.19 # Required for phi3v processor. See https://github.com/pytorch/vision?tab=readme-ov-file#installation for corresponding version
|
torchvision == 0.19 # Required for phi3v processor. See https://github.com/pytorch/vision?tab=readme-ov-file#installation for corresponding version
|
||||||
xformers == 0.0.27.post2; platform_system == 'Linux' and platform_machine == 'x86_64' # Requires PyTorch 2.4.0
|
xformers == 0.0.27.post2; platform_system == 'Linux' and platform_machine == 'x86_64' # Requires PyTorch 2.4.0
|
||||||
vllm-flash-attn == 2.6.1; platform_system == 'Linux' and platform_machine == 'x86_64' # Requires PyTorch 2.4.0
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
yapf==0.32.0
|
yapf==0.32.0
|
||||||
toml==0.10.2
|
toml==0.10.2
|
||||||
tomli==2.0.1
|
tomli==2.0.1
|
||||||
ruff==0.1.5
|
ruff==0.6.5
|
||||||
codespell==2.3.0
|
codespell==2.3.0
|
||||||
isort==5.13.2
|
isort==5.13.2
|
||||||
clang-format==18.1.5
|
clang-format==18.1.5
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
-r requirements-common.txt
|
-r requirements-common.txt
|
||||||
|
|
||||||
# Dependencies for Neuron devices
|
# Dependencies for Neuron devices
|
||||||
transformers-neuronx >= 0.9.0
|
transformers-neuronx >= 0.12.0
|
||||||
torch-neuronx >= 2.1.0
|
torch-neuronx >= 2.1.2
|
||||||
neuronx-cc
|
neuronx-cc
|
||||||
|
|||||||
@@ -14,13 +14,14 @@ librosa # required for audio test
|
|||||||
opencv-python # required for video test
|
opencv-python # required for video test
|
||||||
peft
|
peft
|
||||||
requests
|
requests
|
||||||
ray[adag]>=2.35
|
ray[adag]==2.35
|
||||||
sentence-transformers # required for embedding
|
sentence-transformers # required for embedding
|
||||||
soundfile # required for audio test
|
soundfile # required for audio test
|
||||||
compressed-tensors==0.4.0 # required for compressed-tensors
|
compressed-tensors==0.4.0 # required for compressed-tensors
|
||||||
timm # required for internvl test
|
timm # required for internvl test
|
||||||
transformers_stream_generator # required for qwen-vl test
|
transformers_stream_generator # required for qwen-vl test
|
||||||
matplotlib # required for qwen-vl test
|
matplotlib # required for qwen-vl test
|
||||||
|
datamodel_code_generator # required for minicpm3 test
|
||||||
|
|
||||||
# TODO: Add this after fully implementing llava(mantis)
|
# TODO: Add this after fully implementing llava(mantis)
|
||||||
# git+https://github.com/TIGER-AI-Lab/Mantis.git # required for llava(mantis) test
|
# git+https://github.com/TIGER-AI-Lab/Mantis.git # required for llava(mantis) test
|
||||||
@@ -29,5 +30,5 @@ matplotlib # required for qwen-vl test
|
|||||||
aiohttp
|
aiohttp
|
||||||
|
|
||||||
# quantization
|
# quantization
|
||||||
bitsandbytes==0.42.0
|
bitsandbytes>=0.44.0
|
||||||
buildkite-test-collector==0.1.8
|
buildkite-test-collector==0.1.8
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
setuptools < 70.0.0 # IPEX's torch have some dependency. to be removed.
|
setuptools < 70.0.0 # IPEX's torch have some dependency. to be removed.
|
||||||
|
|
||||||
torch @ https://intel-extension-for-pytorch.s3.amazonaws.com/ipex_dev/xpu/torch-2.1.0.post1%2Bcxx11.abi-cp310-cp310-linux_x86_64.whl
|
ray >= 2.9
|
||||||
intel_extension_for_pytorch @ https://intel-extension-for-pytorch.s3.amazonaws.com/ipex_dev/xpu/intel_extension_for_pytorch-2.1.30a0-cp310-cp310-linux_x86_64.whl
|
# Following pkgs retrieved from https://pytorch-extension.intel.com/release-whl/stable/xpu/us/
|
||||||
oneccl_bind_pt @ https://intel-extension-for-pytorch.s3.amazonaws.com/ipex_stable/xpu/oneccl_bind_pt-2.1.200%2Bxpu-cp310-cp310-linux_x86_64.whl
|
torch == 2.3.1+cxx11.abi
|
||||||
|
intel-extension-for-pytorch == 2.3.110+xpu
|
||||||
triton @ https://github.com/intel/intel-xpu-backend-for-triton/releases/download/v2.1.0/triton-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
|
oneccl_bind_pt == 2.3.100+xpu
|
||||||
|
|
||||||
|
triton-xpu == 3.0.0b2
|
||||||
|
|||||||
123
setup.py
123
setup.py
@@ -5,7 +5,7 @@ import os
|
|||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
from pathlib import Path
|
||||||
from shutil import which
|
from shutil import which
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ import torch
|
|||||||
from packaging.version import Version, parse
|
from packaging.version import Version, parse
|
||||||
from setuptools import Extension, find_packages, setup
|
from setuptools import Extension, find_packages, setup
|
||||||
from setuptools.command.build_ext import build_ext
|
from setuptools.command.build_ext import build_ext
|
||||||
|
from setuptools_scm import get_version
|
||||||
from torch.utils.cpp_extension import CUDA_HOME
|
from torch.utils.cpp_extension import CUDA_HOME
|
||||||
|
|
||||||
|
|
||||||
@@ -27,34 +28,6 @@ def load_module_from_path(module_name, path):
|
|||||||
ROOT_DIR = os.path.dirname(__file__)
|
ROOT_DIR = os.path.dirname(__file__)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def embed_commit_hash():
|
|
||||||
try:
|
|
||||||
if "BUILDKITE_COMMIT" in os.environ:
|
|
||||||
# ci build
|
|
||||||
commit_id = os.environ["BUILDKITE_COMMIT"]
|
|
||||||
else:
|
|
||||||
commit_id = subprocess.check_output(["git", "rev-parse", "HEAD"],
|
|
||||||
encoding="utf-8").strip()
|
|
||||||
|
|
||||||
commit_contents = f'__commit__ = "{commit_id}"\n'
|
|
||||||
|
|
||||||
version_file = os.path.join(ROOT_DIR, "vllm", "commit_id.py")
|
|
||||||
with open(version_file, "w", encoding="utf-8") as f:
|
|
||||||
f.write(commit_contents)
|
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
warnings.warn(f"Failed to get commit hash:\n{e}",
|
|
||||||
RuntimeWarning,
|
|
||||||
stacklevel=2)
|
|
||||||
except Exception as e:
|
|
||||||
warnings.warn(f"Failed to embed commit hash:\n{e}",
|
|
||||||
RuntimeWarning,
|
|
||||||
stacklevel=2)
|
|
||||||
|
|
||||||
|
|
||||||
embed_commit_hash()
|
|
||||||
|
|
||||||
# cannot import envs directly because it depends on vllm,
|
# cannot import envs directly because it depends on vllm,
|
||||||
# which is not installed yet
|
# which is not installed yet
|
||||||
envs = load_module_from_path('envs', os.path.join(ROOT_DIR, 'vllm', 'envs.py'))
|
envs = load_module_from_path('envs', os.path.join(ROOT_DIR, 'vllm', 'envs.py'))
|
||||||
@@ -152,15 +125,8 @@ class cmake_build_ext(build_ext):
|
|||||||
default_cfg = "Debug" if self.debug else "RelWithDebInfo"
|
default_cfg = "Debug" if self.debug else "RelWithDebInfo"
|
||||||
cfg = envs.CMAKE_BUILD_TYPE or default_cfg
|
cfg = envs.CMAKE_BUILD_TYPE or default_cfg
|
||||||
|
|
||||||
# where .so files will be written, should be the same for all extensions
|
|
||||||
# that use the same CMakeLists.txt.
|
|
||||||
outdir = os.path.abspath(
|
|
||||||
os.path.dirname(self.get_ext_fullpath(ext.name)))
|
|
||||||
|
|
||||||
cmake_args = [
|
cmake_args = [
|
||||||
'-DCMAKE_BUILD_TYPE={}'.format(cfg),
|
'-DCMAKE_BUILD_TYPE={}'.format(cfg),
|
||||||
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}'.format(outdir),
|
|
||||||
'-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY={}'.format(self.build_temp),
|
|
||||||
'-DVLLM_TARGET_DEVICE={}'.format(VLLM_TARGET_DEVICE),
|
'-DVLLM_TARGET_DEVICE={}'.format(VLLM_TARGET_DEVICE),
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -224,10 +190,12 @@ class cmake_build_ext(build_ext):
|
|||||||
os.makedirs(self.build_temp)
|
os.makedirs(self.build_temp)
|
||||||
|
|
||||||
targets = []
|
targets = []
|
||||||
|
target_name = lambda s: remove_prefix(remove_prefix(s, "vllm."),
|
||||||
|
"vllm_flash_attn.")
|
||||||
# Build all the extensions
|
# Build all the extensions
|
||||||
for ext in self.extensions:
|
for ext in self.extensions:
|
||||||
self.configure(ext)
|
self.configure(ext)
|
||||||
targets.append(remove_prefix(ext.name, "vllm."))
|
targets.append(target_name(ext.name))
|
||||||
|
|
||||||
num_jobs, _ = self.compute_num_jobs()
|
num_jobs, _ = self.compute_num_jobs()
|
||||||
|
|
||||||
@@ -240,6 +208,43 @@ class cmake_build_ext(build_ext):
|
|||||||
|
|
||||||
subprocess.check_call(["cmake", *build_args], cwd=self.build_temp)
|
subprocess.check_call(["cmake", *build_args], cwd=self.build_temp)
|
||||||
|
|
||||||
|
# Install the libraries
|
||||||
|
for ext in self.extensions:
|
||||||
|
# Install the extension into the proper location
|
||||||
|
outdir = Path(self.get_ext_fullpath(ext.name)).parent.absolute()
|
||||||
|
|
||||||
|
# Skip if the install directory is the same as the build directory
|
||||||
|
if outdir == self.build_temp:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# CMake appends the extension prefix to the install path,
|
||||||
|
# and outdir already contains that prefix, so we need to remove it.
|
||||||
|
prefix = outdir
|
||||||
|
for i in range(ext.name.count('.')):
|
||||||
|
prefix = prefix.parent
|
||||||
|
|
||||||
|
# prefix here should actually be the same for all components
|
||||||
|
install_args = [
|
||||||
|
"cmake", "--install", ".", "--prefix", prefix, "--component",
|
||||||
|
target_name(ext.name)
|
||||||
|
]
|
||||||
|
subprocess.check_call(install_args, cwd=self.build_temp)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# First, run the standard build_ext command to compile the extensions
|
||||||
|
super().run()
|
||||||
|
|
||||||
|
# copy vllm/vllm_flash_attn/*.py from self.build_lib to current
|
||||||
|
# directory so that they can be included in the editable build
|
||||||
|
import glob
|
||||||
|
files = glob.glob(
|
||||||
|
os.path.join(self.build_lib, "vllm", "vllm_flash_attn", "*.py"))
|
||||||
|
for file in files:
|
||||||
|
dst_file = os.path.join("vllm/vllm_flash_attn",
|
||||||
|
os.path.basename(file))
|
||||||
|
print(f"Copying {file} to {dst_file}")
|
||||||
|
self.copy_file(file, dst_file)
|
||||||
|
|
||||||
|
|
||||||
def _no_device() -> bool:
|
def _no_device() -> bool:
|
||||||
return VLLM_TARGET_DEVICE == "empty"
|
return VLLM_TARGET_DEVICE == "empty"
|
||||||
@@ -348,50 +353,43 @@ def get_path(*filepath) -> str:
|
|||||||
return os.path.join(ROOT_DIR, *filepath)
|
return os.path.join(ROOT_DIR, *filepath)
|
||||||
|
|
||||||
|
|
||||||
def find_version(filepath: str) -> str:
|
|
||||||
"""Extract version information from the given filepath.
|
|
||||||
|
|
||||||
Adapted from https://github.com/ray-project/ray/blob/0b190ee1160eeca9796bc091e07eaebf4c85b511/python/setup.py
|
|
||||||
"""
|
|
||||||
with open(filepath) as fp:
|
|
||||||
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
|
|
||||||
fp.read(), re.M)
|
|
||||||
if version_match:
|
|
||||||
return version_match.group(1)
|
|
||||||
raise RuntimeError("Unable to find version string.")
|
|
||||||
|
|
||||||
|
|
||||||
def get_vllm_version() -> str:
|
def get_vllm_version() -> str:
|
||||||
version = find_version(get_path("vllm", "version.py"))
|
version = get_version(
|
||||||
|
write_to="vllm/_version.py", # TODO: move this to pyproject.toml
|
||||||
|
)
|
||||||
|
|
||||||
|
sep = "+" if "+" not in version else "." # dev versions might contain +
|
||||||
|
|
||||||
if _no_device():
|
if _no_device():
|
||||||
if envs.VLLM_TARGET_DEVICE == "empty":
|
if envs.VLLM_TARGET_DEVICE == "empty":
|
||||||
version += "+empty"
|
version += f"{sep}empty"
|
||||||
elif _is_cuda():
|
elif _is_cuda():
|
||||||
cuda_version = str(get_nvcc_cuda_version())
|
cuda_version = str(get_nvcc_cuda_version())
|
||||||
if cuda_version != MAIN_CUDA_VERSION:
|
if cuda_version != MAIN_CUDA_VERSION:
|
||||||
cuda_version_str = cuda_version.replace(".", "")[:3]
|
cuda_version_str = cuda_version.replace(".", "")[:3]
|
||||||
version += f"+cu{cuda_version_str}"
|
# skip this for source tarball, required for pypi
|
||||||
|
if "sdist" not in sys.argv:
|
||||||
|
version += f"{sep}cu{cuda_version_str}"
|
||||||
elif _is_hip():
|
elif _is_hip():
|
||||||
# Get the HIP version
|
# Get the HIP version
|
||||||
hipcc_version = get_hipcc_rocm_version()
|
hipcc_version = get_hipcc_rocm_version()
|
||||||
if hipcc_version != MAIN_CUDA_VERSION:
|
if hipcc_version != MAIN_CUDA_VERSION:
|
||||||
rocm_version_str = hipcc_version.replace(".", "")[:3]
|
rocm_version_str = hipcc_version.replace(".", "")[:3]
|
||||||
version += f"+rocm{rocm_version_str}"
|
version += f"{sep}rocm{rocm_version_str}"
|
||||||
elif _is_neuron():
|
elif _is_neuron():
|
||||||
# Get the Neuron version
|
# Get the Neuron version
|
||||||
neuron_version = str(get_neuronxcc_version())
|
neuron_version = str(get_neuronxcc_version())
|
||||||
if neuron_version != MAIN_CUDA_VERSION:
|
if neuron_version != MAIN_CUDA_VERSION:
|
||||||
neuron_version_str = neuron_version.replace(".", "")[:3]
|
neuron_version_str = neuron_version.replace(".", "")[:3]
|
||||||
version += f"+neuron{neuron_version_str}"
|
version += f"{sep}neuron{neuron_version_str}"
|
||||||
elif _is_openvino():
|
elif _is_openvino():
|
||||||
version += "+openvino"
|
version += f"{sep}openvino"
|
||||||
elif _is_tpu():
|
elif _is_tpu():
|
||||||
version += "+tpu"
|
version += f"{sep}tpu"
|
||||||
elif _is_cpu():
|
elif _is_cpu():
|
||||||
version += "+cpu"
|
version += f"{sep}cpu"
|
||||||
elif _is_xpu():
|
elif _is_xpu():
|
||||||
version += "+xpu"
|
version += f"{sep}xpu"
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Unknown runtime environment")
|
raise RuntimeError("Unknown runtime environment")
|
||||||
|
|
||||||
@@ -462,6 +460,13 @@ if _build_core_ext():
|
|||||||
if _is_cuda() or _is_hip():
|
if _is_cuda() or _is_hip():
|
||||||
ext_modules.append(CMakeExtension(name="vllm._moe_C"))
|
ext_modules.append(CMakeExtension(name="vllm._moe_C"))
|
||||||
|
|
||||||
|
if _is_hip():
|
||||||
|
ext_modules.append(CMakeExtension(name="vllm._rocm_C"))
|
||||||
|
|
||||||
|
if _is_cuda():
|
||||||
|
ext_modules.append(
|
||||||
|
CMakeExtension(name="vllm.vllm_flash_attn.vllm_flash_attn_c"))
|
||||||
|
|
||||||
if _build_custom_ops():
|
if _build_custom_ops():
|
||||||
ext_modules.append(CMakeExtension(name="vllm._C"))
|
ext_modules.append(CMakeExtension(name="vllm._C"))
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import os
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
@@ -26,8 +25,7 @@ def _query_server_long(prompt: str) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def api_server(tokenizer_pool_size: int, engine_use_ray: bool,
|
def api_server(tokenizer_pool_size: int, worker_use_ray: bool):
|
||||||
worker_use_ray: bool):
|
|
||||||
script_path = Path(__file__).parent.joinpath(
|
script_path = Path(__file__).parent.joinpath(
|
||||||
"api_server_async_engine.py").absolute()
|
"api_server_async_engine.py").absolute()
|
||||||
commands = [
|
commands = [
|
||||||
@@ -37,25 +35,17 @@ def api_server(tokenizer_pool_size: int, engine_use_ray: bool,
|
|||||||
str(tokenizer_pool_size)
|
str(tokenizer_pool_size)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Copy the environment variables and append `VLLM_ALLOW_ENGINE_USE_RAY=1`
|
|
||||||
# to prevent `--engine-use-ray` raises an exception due to it deprecation
|
|
||||||
env_vars = os.environ.copy()
|
|
||||||
env_vars["VLLM_ALLOW_ENGINE_USE_RAY"] = "1"
|
|
||||||
|
|
||||||
if engine_use_ray:
|
|
||||||
commands.append("--engine-use-ray")
|
|
||||||
if worker_use_ray:
|
if worker_use_ray:
|
||||||
commands.append("--worker-use-ray")
|
commands.append("--worker-use-ray")
|
||||||
uvicorn_process = subprocess.Popen(commands, env=env_vars)
|
uvicorn_process = subprocess.Popen(commands)
|
||||||
yield
|
yield
|
||||||
uvicorn_process.terminate()
|
uvicorn_process.terminate()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("tokenizer_pool_size", [0, 2])
|
@pytest.mark.parametrize("tokenizer_pool_size", [0, 2])
|
||||||
@pytest.mark.parametrize("worker_use_ray", [False, True])
|
@pytest.mark.parametrize("worker_use_ray", [False, True])
|
||||||
@pytest.mark.parametrize("engine_use_ray", [False, True])
|
def test_api_server(api_server, tokenizer_pool_size: int,
|
||||||
def test_api_server(api_server, tokenizer_pool_size: int, worker_use_ray: bool,
|
worker_use_ray: bool):
|
||||||
engine_use_ray: bool):
|
|
||||||
"""
|
"""
|
||||||
Run the API server and test it.
|
Run the API server and test it.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
|
import uuid
|
||||||
from asyncio import CancelledError
|
from asyncio import CancelledError
|
||||||
|
from copy import copy
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import pytest_asyncio
|
import pytest_asyncio
|
||||||
@@ -12,6 +14,7 @@ from vllm import SamplingParams
|
|||||||
from vllm.config import ParallelConfig
|
from vllm.config import ParallelConfig
|
||||||
from vllm.engine.async_llm_engine import AsyncEngineArgs, AsyncLLMEngine
|
from vllm.engine.async_llm_engine import AsyncEngineArgs, AsyncLLMEngine
|
||||||
from vllm.outputs import RequestOutput as RealRequestOutput
|
from vllm.outputs import RequestOutput as RealRequestOutput
|
||||||
|
from vllm.sampling_params import RequestOutputKind
|
||||||
|
|
||||||
from ..conftest import cleanup
|
from ..conftest import cleanup
|
||||||
from ..utils import wait_for_gpu_memory_to_clear
|
from ..utils import wait_for_gpu_memory_to_clear
|
||||||
@@ -23,6 +26,11 @@ class RequestOutput:
|
|||||||
finished: bool = False
|
finished: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MockModelConfig:
|
||||||
|
use_async_output_proc = True
|
||||||
|
|
||||||
|
|
||||||
class MockEngine:
|
class MockEngine:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -32,6 +40,7 @@ class MockEngine:
|
|||||||
self.request_id = None
|
self.request_id = None
|
||||||
# Ugly, remove dependency when possible
|
# Ugly, remove dependency when possible
|
||||||
self.parallel_config = ParallelConfig(1, 1, False)
|
self.parallel_config = ParallelConfig(1, 1, False)
|
||||||
|
self.model_config = MockModelConfig()
|
||||||
|
|
||||||
async def step_async(self, virtual_engine):
|
async def step_async(self, virtual_engine):
|
||||||
# PP size is 1, ignore virtual engine
|
# PP size is 1, ignore virtual engine
|
||||||
@@ -72,14 +81,12 @@ class MockEngine:
|
|||||||
|
|
||||||
|
|
||||||
class MockAsyncLLMEngine(AsyncLLMEngine):
|
class MockAsyncLLMEngine(AsyncLLMEngine):
|
||||||
|
_engine_class = MockEngine
|
||||||
def _init_engine(self, *args, **kwargs):
|
|
||||||
return MockEngine()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_new_requests_event():
|
async def test_new_requests_event():
|
||||||
engine = MockAsyncLLMEngine(worker_use_ray=False, engine_use_ray=False)
|
engine = MockAsyncLLMEngine()
|
||||||
engine.start_background_loop()
|
engine.start_background_loop()
|
||||||
await asyncio.sleep(0.01)
|
await asyncio.sleep(0.01)
|
||||||
assert engine.engine.step_calls == 0
|
assert engine.engine.step_calls == 0
|
||||||
@@ -112,16 +119,11 @@ async def test_new_requests_event():
|
|||||||
assert engine.engine.add_request_calls == 3
|
assert engine.engine.add_request_calls == 3
|
||||||
assert engine.engine.step_calls == old_step_calls + 1
|
assert engine.engine.step_calls == old_step_calls + 1
|
||||||
|
|
||||||
# Allow deprecated engine_use_ray to not raise exception
|
engine = MockAsyncLLMEngine()
|
||||||
os.environ["VLLM_ALLOW_ENGINE_USE_RAY"] = "1"
|
|
||||||
|
|
||||||
engine = MockAsyncLLMEngine(worker_use_ray=True, engine_use_ray=True)
|
|
||||||
assert engine.get_model_config() is not None
|
assert engine.get_model_config() is not None
|
||||||
assert engine.get_tokenizer() is not None
|
assert engine.get_tokenizer() is not None
|
||||||
assert engine.get_decoding_config() is not None
|
assert engine.get_decoding_config() is not None
|
||||||
|
|
||||||
os.environ.pop("VLLM_ALLOW_ENGINE_USE_RAY")
|
|
||||||
|
|
||||||
|
|
||||||
def start_engine():
|
def start_engine():
|
||||||
wait_for_gpu_memory_to_clear(
|
wait_for_gpu_memory_to_clear(
|
||||||
@@ -130,8 +132,17 @@ def start_engine():
|
|||||||
timeout_s=60,
|
timeout_s=60,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
num_scheduler_steps = int(os.getenv("NUM_SCHEDULER_STEPS", "1"))
|
||||||
|
print(f"Starting engine with num_scheduler_steps={num_scheduler_steps}")
|
||||||
|
|
||||||
return AsyncLLMEngine.from_engine_args(
|
return AsyncLLMEngine.from_engine_args(
|
||||||
AsyncEngineArgs(model="facebook/opt-125m", enforce_eager=True))
|
AsyncEngineArgs(model="facebook/opt-125m",
|
||||||
|
enforce_eager=True,
|
||||||
|
num_scheduler_steps=num_scheduler_steps))
|
||||||
|
|
||||||
|
|
||||||
|
def uid() -> str:
|
||||||
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="module")
|
@pytest_asyncio.fixture(scope="module")
|
||||||
@@ -154,59 +165,195 @@ def should_do_global_cleanup_after_test(request) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio(scope="module")
|
@pytest.mark.asyncio(scope="module")
|
||||||
async def test_asyncio_run(async_engine):
|
@pytest.mark.parametrize("stop", [None, ["a stop string"]])
|
||||||
|
async def test_asyncio_run(async_engine, stop):
|
||||||
|
|
||||||
|
scheduler_config = await async_engine.get_scheduler_config()
|
||||||
|
num_scheduler_steps = scheduler_config.num_scheduler_steps
|
||||||
|
|
||||||
async def run(prompt: str):
|
async def run(prompt: str):
|
||||||
sampling_params = SamplingParams(
|
sampling_params = SamplingParams(
|
||||||
temperature=0,
|
temperature=0,
|
||||||
max_tokens=32,
|
max_tokens=32,
|
||||||
|
min_tokens=32,
|
||||||
|
stop=stop,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
output_count = 0
|
||||||
|
final_output = None
|
||||||
async for output in async_engine.generate(prompt,
|
async for output in async_engine.generate(prompt,
|
||||||
sampling_params,
|
sampling_params,
|
||||||
request_id=prompt):
|
request_id=uid()):
|
||||||
|
output_count += 1
|
||||||
final_output = output
|
final_output = output
|
||||||
return final_output
|
return final_output, output_count
|
||||||
|
|
||||||
results = await asyncio.gather(
|
results = await asyncio.gather(
|
||||||
run("test0"),
|
run("test0"),
|
||||||
run("test1"),
|
run("test0"),
|
||||||
)
|
)
|
||||||
assert len(results) == 2
|
assert len(results) == 2
|
||||||
|
first, second = results
|
||||||
|
|
||||||
|
# remove nondeterministic fields for comparison
|
||||||
|
first[0].metrics = None
|
||||||
|
second[0].metrics = None
|
||||||
|
first[0].request_id = None
|
||||||
|
second[0].request_id = None
|
||||||
|
|
||||||
|
assert str(first) == str(second)
|
||||||
|
|
||||||
|
output_count = results[0][1]
|
||||||
|
if num_scheduler_steps == 1:
|
||||||
|
assert output_count == 32
|
||||||
|
else:
|
||||||
|
assert 1 < output_count < 32
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio(scope="module")
|
@pytest.mark.asyncio(scope="module")
|
||||||
async def test_cancellation(async_engine):
|
@pytest.mark.parametrize("stop", [None, ["a stop string"]])
|
||||||
|
async def test_output_kinds(async_engine, stop):
|
||||||
|
"""Test that output_kind works as expected and that
|
||||||
|
results are equivalent across different kinds."""
|
||||||
|
|
||||||
|
scheduler_config = await async_engine.get_scheduler_config()
|
||||||
|
num_scheduler_steps = scheduler_config.num_scheduler_steps
|
||||||
|
|
||||||
sampling_params = SamplingParams(
|
sampling_params = SamplingParams(
|
||||||
temperature=0,
|
temperature=0,
|
||||||
min_tokens=10,
|
max_tokens=32,
|
||||||
max_tokens=10,
|
min_tokens=32,
|
||||||
|
stop=stop,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def run(prompt: str, kind: RequestOutputKind):
|
||||||
|
params = copy(sampling_params)
|
||||||
|
params.output_kind = kind
|
||||||
|
|
||||||
|
output_count = 0
|
||||||
|
final_output = None
|
||||||
|
async for output in async_engine.generate(prompt,
|
||||||
|
params,
|
||||||
|
request_id=uid()):
|
||||||
|
output_count += 1
|
||||||
|
final_output = output
|
||||||
|
|
||||||
|
assert final_output is not None
|
||||||
|
assert final_output.finished
|
||||||
|
|
||||||
|
return (final_output.prompt_token_ids,
|
||||||
|
final_output.outputs[0].token_ids,
|
||||||
|
final_output.outputs[0].text, output_count)
|
||||||
|
|
||||||
|
async def run_deltas(prompt: str):
|
||||||
|
params = copy(sampling_params)
|
||||||
|
params.output_kind = RequestOutputKind.DELTA
|
||||||
|
|
||||||
|
prompt_tokens = None
|
||||||
|
output_tokens: List[int] = []
|
||||||
|
output_text = ""
|
||||||
|
output_count = 0
|
||||||
|
final_output = None
|
||||||
|
async for output in async_engine.generate(prompt,
|
||||||
|
params,
|
||||||
|
request_id=uid()):
|
||||||
|
token_ids = output.outputs[0].token_ids
|
||||||
|
text = output.outputs[0].text
|
||||||
|
final_output = output
|
||||||
|
|
||||||
|
# Ensure we get prompt ids iff we haven't yet received output tokens
|
||||||
|
if output_tokens:
|
||||||
|
assert 1 <= len(token_ids) <= num_scheduler_steps
|
||||||
|
assert stop or text
|
||||||
|
assert not output.prompt_token_ids
|
||||||
|
else:
|
||||||
|
assert output.prompt_token_ids
|
||||||
|
prompt_tokens = output.prompt_token_ids
|
||||||
|
|
||||||
|
output_tokens.extend(token_ids)
|
||||||
|
output_text += text
|
||||||
|
|
||||||
|
output_count += 1
|
||||||
|
|
||||||
|
assert final_output is not None
|
||||||
|
assert final_output.finished
|
||||||
|
|
||||||
|
return prompt_tokens, output_tokens, output_text, output_count
|
||||||
|
|
||||||
|
results = await asyncio.gather(
|
||||||
|
run("common input prompt", RequestOutputKind.CUMULATIVE),
|
||||||
|
run("common input prompt", RequestOutputKind.FINAL_ONLY),
|
||||||
|
run_deltas("common input prompt"))
|
||||||
|
|
||||||
|
# Make sure outputs are the same
|
||||||
|
prompt_set = set(tuple(prompt_ids) for prompt_ids, _, _, _ in results)
|
||||||
|
assert len(prompt_set) == 1
|
||||||
|
|
||||||
|
text_set = set(text for _, _, text, _ in results)
|
||||||
|
assert len(text_set) == 1
|
||||||
|
|
||||||
|
tokens_set = set(tuple(ids) for _, ids, _, _ in results)
|
||||||
|
assert len(tokens_set) == 1
|
||||||
|
|
||||||
|
cumulative, final, deltas = results
|
||||||
|
|
||||||
|
# output message counts
|
||||||
|
assert cumulative[3] == deltas[3]
|
||||||
|
|
||||||
|
if num_scheduler_steps == 1:
|
||||||
|
assert cumulative[3] == 32
|
||||||
|
else:
|
||||||
|
assert 1 < cumulative[3] < 32
|
||||||
|
|
||||||
|
assert final[3] == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio(scope="module")
|
||||||
|
@pytest.mark.parametrize("stop", [None, ["a stop string"]])
|
||||||
|
async def test_cancellation(async_engine, stop):
|
||||||
|
scheduler_config = await async_engine.get_scheduler_config()
|
||||||
|
num_scheduler_steps = scheduler_config.num_scheduler_steps
|
||||||
|
|
||||||
|
sampling_params = SamplingParams(
|
||||||
|
temperature=0,
|
||||||
|
min_tokens=13,
|
||||||
|
max_tokens=13,
|
||||||
|
stop=stop,
|
||||||
|
)
|
||||||
|
|
||||||
|
stop_at = 5 if num_scheduler_steps == 1 else 1
|
||||||
|
|
||||||
|
request_id = uid()
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
with pytest.raises(CancelledError):
|
with pytest.raises(CancelledError):
|
||||||
async for output in async_engine.generate("test2",
|
async for output in async_engine.generate("test2",
|
||||||
sampling_params,
|
sampling_params,
|
||||||
request_id="test2"):
|
request_id=request_id):
|
||||||
assert not output.finished
|
assert not output.finished
|
||||||
i += 1
|
i += 1
|
||||||
if i == 5:
|
if i == stop_at:
|
||||||
await async_engine.abort("test2")
|
await async_engine.abort(request_id)
|
||||||
|
|
||||||
assert i == 5
|
assert i == stop_at
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio(scope="module")
|
@pytest.mark.asyncio(scope="module")
|
||||||
async def test_delayed_generator(async_engine):
|
@pytest.mark.parametrize("stop", [None, ["a stop string"]])
|
||||||
|
async def test_delayed_generator(async_engine, stop):
|
||||||
|
scheduler_config = await async_engine.get_scheduler_config()
|
||||||
|
|
||||||
|
if scheduler_config.num_scheduler_steps != 1:
|
||||||
|
pytest.skip("no need to test this one with multistep")
|
||||||
|
|
||||||
sampling_params = SamplingParams(
|
sampling_params = SamplingParams(
|
||||||
temperature=0,
|
temperature=0,
|
||||||
min_tokens=10,
|
min_tokens=10,
|
||||||
max_tokens=10,
|
max_tokens=10,
|
||||||
|
stop=stop,
|
||||||
)
|
)
|
||||||
|
|
||||||
stream = async_engine.generate("test3",
|
stream = async_engine.generate("test3", sampling_params, request_id=uid())
|
||||||
sampling_params,
|
|
||||||
request_id="test3")
|
|
||||||
i = 0
|
i = 0
|
||||||
final_output: Optional[RealRequestOutput] = None
|
final_output: Optional[RealRequestOutput] = None
|
||||||
async for output in stream:
|
async for output in stream:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user