forked from Karylab-cklius/vllm
[CPU] Fix macOS/Apple Silicon hang by enabling OpenMP in the build (#46769)
Signed-off-by: mgoin <mgoin64@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
3d3b96488f
commit
c6554f321c
@@ -3,3 +3,5 @@
|
||||
self-hosted-runner:
|
||||
labels:
|
||||
- vllm-runners
|
||||
# Not yet in actionlint's known-label set.
|
||||
- macos-26
|
||||
|
||||
@@ -11,7 +11,19 @@ permissions:
|
||||
|
||||
jobs:
|
||||
macos-m1-smoke-test:
|
||||
runs-on: macos-latest
|
||||
# macos-26 (the supported target) is still a preview runner, so gate on GA
|
||||
# macos-15 and keep macos-26 non-blocking.
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-15
|
||||
required: true
|
||||
- os: macos-26
|
||||
required: false
|
||||
name: macos-m1-smoke-test (${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ !matrix.required }}
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
@@ -72,14 +84,11 @@ jobs:
|
||||
# Test health endpoint
|
||||
curl -f http://localhost:8000/health
|
||||
|
||||
# Test completion
|
||||
curl -f http://localhost:8000/v1/completions \
|
||||
# Long prompt: hits the split-KV path that short prompts skip (#46769).
|
||||
PAYLOAD=$(python -c "import json; print(json.dumps({'model': 'Qwen/Qwen3-0.6B', 'prompt': 'The quick brown fox jumps over the lazy dog. ' * 24, 'max_tokens': 16}))")
|
||||
curl -f --max-time 120 http://localhost:8000/v1/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "Qwen/Qwen3-0.6B",
|
||||
"prompt": "Hello",
|
||||
"max_tokens": 5
|
||||
}'
|
||||
-d "$PAYLOAD"
|
||||
|
||||
# Cleanup
|
||||
kill "$SERVER_PID"
|
||||
|
||||
@@ -24,7 +24,10 @@ set (ENABLE_NUMA TRUE)
|
||||
# Check the compile flags
|
||||
#
|
||||
if(MACOSX_FOUND)
|
||||
# Apple clang needs -Xpreprocessor to enable OpenMP. No runtime link is
|
||||
# needed: _C is a dynamic_lookup bundle and resolves libomp from torch.
|
||||
list(APPEND CXX_COMPILE_FLAGS
|
||||
"-Xpreprocessor" "-fopenmp"
|
||||
"-DVLLM_CPU_EXTENSION")
|
||||
else()
|
||||
list(APPEND CXX_COMPILE_FLAGS
|
||||
|
||||
@@ -124,7 +124,7 @@ struct AttentionMetadata {
|
||||
workitem_group_num(workitem_group_num),
|
||||
reduction_item_num(reduction_item_num),
|
||||
reduction_split_num(reduction_split_num),
|
||||
thread_num(omp_get_max_threads()),
|
||||
thread_num(cpu_utils::get_max_threads()),
|
||||
effective_thread_num(thread_num),
|
||||
split_kv_q_token_num_threshold(split_kv_q_token_num_threshold),
|
||||
attention_scratchpad_size_per_thread(0),
|
||||
@@ -405,7 +405,7 @@ class AttentionScheduler {
|
||||
torch::Tensor schedule(const ScheduleInput& input) const {
|
||||
const bool causal = input.causal;
|
||||
const bool is_dynamic_causal = input.dynamic_causal != nullptr;
|
||||
const int32_t thread_num = omp_get_max_threads();
|
||||
const int32_t thread_num = cpu_utils::get_max_threads();
|
||||
const int64_t cache_size = cpu_utils::get_available_l2_size();
|
||||
const int32_t max_num_q_per_iter = input.max_num_q_per_iter;
|
||||
const int32_t kv_len_alignment = input.kv_block_alignment;
|
||||
@@ -1423,7 +1423,7 @@ class AttentionMainLoop {
|
||||
|
||||
public:
|
||||
void operator()(const AttentionInput* input) {
|
||||
const int thread_num = omp_get_max_threads();
|
||||
const int thread_num = cpu_utils::get_max_threads();
|
||||
TORCH_CHECK_EQ(input->metadata->thread_num, thread_num);
|
||||
std::atomic<int32_t> guard_counter(0);
|
||||
std::atomic<int32_t>* guard_counter_ptr = &guard_counter;
|
||||
|
||||
@@ -267,7 +267,7 @@ void fused_moe_impl(scalar_t* __restrict__ output, scalar_t* __restrict__ input,
|
||||
TORCH_CHECK_EQ(output_size_2 % gemm_n_tile_size, 0);
|
||||
TORCH_CHECK_EQ(output_size_13 / 2, input_size_2);
|
||||
|
||||
const int32_t thread_num = omp_get_max_threads();
|
||||
const int32_t thread_num = cpu_utils::get_max_threads();
|
||||
|
||||
const int32_t w13_input_buffer_size = cpu_utils::round_up<64>(
|
||||
gemm_m_tile_size * input_size_13 * sizeof(scalar_t));
|
||||
|
||||
@@ -25,4 +25,20 @@
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include <c10/util/Exception.h>
|
||||
|
||||
namespace cpu_utils {
|
||||
// Without OpenMP the omp pragmas compile to serial loops, so report 1: kernels
|
||||
// that barrier on the thread count would otherwise deadlock.
|
||||
inline int get_max_threads() {
|
||||
#ifdef _OPENMP
|
||||
return omp_get_max_threads();
|
||||
#else
|
||||
TORCH_WARN_ONCE(
|
||||
"vLLM CPU was built without OpenMP; running single-threaded.");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
} // namespace cpu_utils
|
||||
|
||||
#endif
|
||||
@@ -155,7 +155,7 @@ void cpu_gemm_wna16_impl(
|
||||
constexpr int32_t gemm_m_tile_size = gemm_t::MaxMSize;
|
||||
constexpr int32_t n_block_size = 16;
|
||||
static_assert(gemm_n_tile_size % n_block_size == 0);
|
||||
const int32_t thread_num = omp_get_max_threads();
|
||||
const int32_t thread_num = cpu_utils::get_max_threads();
|
||||
|
||||
// a simple schedule policy, just to hold more B tiles in L2 and make sure
|
||||
// each thread has tasks
|
||||
|
||||
@@ -202,7 +202,7 @@ void dynamic_quant_epilogue(const float* input, scalar_t* output,
|
||||
using cvt_vec_t = typename KernelVecType<scalar_t>::cvt_vec_type;
|
||||
constexpr int vec_elem_num = load_vec_t::VEC_ELEM_NUM;
|
||||
|
||||
const int64_t thread_num = omp_get_max_threads();
|
||||
const int64_t thread_num = cpu_utils::get_max_threads();
|
||||
if (num_tokens > thread_num) {
|
||||
#pragma omp parallel for
|
||||
for (int64_t i = 0; i < num_tokens; ++i) {
|
||||
|
||||
@@ -251,7 +251,7 @@ void mla_decode_kvcache_cpu_impl(
|
||||
constexpr int QK_NUM_ELEM = qk_vec_type::VEC_ELEM_NUM;
|
||||
|
||||
// shared across threads
|
||||
const int max_threads = omp_get_max_threads();
|
||||
const int max_threads = cpu_utils::get_max_threads();
|
||||
const int acc_out_nbytes =
|
||||
max_threads * num_heads * V_HEAD_DIM * sizeof(float);
|
||||
float* acc_out = static_cast<float*>(std::aligned_alloc(64, acc_out_nbytes));
|
||||
|
||||
@@ -15,6 +15,10 @@ Currently the CPU implementation for macOS supports FP32 and FP16 datatypes.
|
||||
- SDK: `XCode 15.4` or later with Command Line Tools
|
||||
- Compiler: `Apple Clang >= 15.0.0`
|
||||
|
||||
!!! note
|
||||
The macOS CPU build is smoke-tested in CI on the latest GA Apple Silicon
|
||||
runner; other macOS or Apple Clang versions are best-effort.
|
||||
|
||||
--8<-- [end:requirements]
|
||||
--8<-- [start:set-up-using-python]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user