Implement Qwen text core

This commit is contained in:
Georg Bauer
2026-09-03 20:31:53 +02:00
parent 3773cfda2e
commit c414640050
9 changed files with 2766 additions and 52 deletions

View File

@@ -128,6 +128,30 @@ int ds4_gpu_set_aux_model_map_range(const void *model_map,
uint64_t map_offset,
uint64_t map_size);
int ds4_gpu_set_model_map_spans(const void *model_map, uint64_t model_size, const uint64_t *offsets, const uint64_t *sizes, uint32_t count, uint64_t max_tensor_bytes);
typedef struct {
const void *map;
uint64_t size;
uint64_t offset;
uint64_t bytes;
} ds4_gpu_qwen_weight_view;
typedef struct {
uint32_t u[16];
float f[8];
} ds4_gpu_qwen_kernel_args;
int ds4_gpu_qwen_dispatch(
const char *kernel,
ds4_gpu_tensor *out,
const ds4_gpu_tensor *a,
const ds4_gpu_tensor *b,
const ds4_gpu_tensor *c,
const ds4_gpu_qwen_weight_view *weights,
uint32_t weight_count,
const ds4_gpu_qwen_kernel_args *args,
uint32_t grid_x,
uint32_t grid_y);
int ds4_gpu_cache_model_range(const void *model_map, uint64_t model_size, uint64_t offset, uint64_t bytes, const char *label);
int ds4_gpu_cache_q8_f16_range(const void *model_map, uint64_t model_size, uint64_t offset, uint64_t bytes, uint64_t in_dim, uint64_t out_dim, const char *label);
int ds4_gpu_q8_cache_suppressed(void);

View File

@@ -4359,6 +4359,7 @@ static NSString *ds4_gpu_full_source(void) {
@[@"DS4_METAL_GLM53_BF16_SOURCE", @"metal/glm53_bf16.metal"],
@[@"DS4_METAL_GLM53_VISION_SOURCE", @"metal/glm53_vision.metal"],
@[@"DS4_METAL_GLM53_KDA_SOURCE", @"metal/glm53_kda.metal"],
@[@"DS4_METAL_QWEN38_SOURCE", @"metal/qwen38.metal"],
@[@"DS4_METAL_MOE_SOURCE", @"metal/moe.metal"],
@[@"DS4_METAL_DSV4_HC_SOURCE", @"metal/dsv4_hc.metal"],
@[@"DS4_METAL_UNARY_SOURCE", @"metal/unary.metal"],
@@ -11737,6 +11738,68 @@ static id<MTLBuffer> ds4_gpu_wrap_model_exact_range_owned(
DS4_GPU_EXACT_VIEW_OWNED);
}
int ds4_gpu_qwen_dispatch(
const char *kernel,
ds4_gpu_tensor *out,
const ds4_gpu_tensor *a,
const ds4_gpu_tensor *b,
const ds4_gpu_tensor *c,
const ds4_gpu_qwen_weight_view *weights,
uint32_t weight_count,
const ds4_gpu_qwen_kernel_args *args,
uint32_t grid_x,
uint32_t grid_y) {
if (!kernel || !out || !args || grid_x == 0 || grid_y == 0 ||
weight_count > 3 || (weight_count != 0 && !weights)) {
return 0;
}
id<MTLComputePipelineState> pipeline = ds4_gpu_get_pipeline(kernel);
if (!pipeline) return 0;
int owned = 0;
id<MTLCommandBuffer> cb = ds4_gpu_command_buffer(&owned);
if (!cb) return 0;
id<MTLComputeCommandEncoder> enc = ds4_gpu_compute_encoder(cb);
if (!enc) return 0;
[enc setComputePipelineState:pipeline];
[enc setBytes:args length:sizeof(*args) atIndex:0];
const DS4MetalTensor *tensors[4] = {
ds4_gpu_tensor_const_obj(out),
a ? ds4_gpu_tensor_const_obj(a) : nil,
b ? ds4_gpu_tensor_const_obj(b) : nil,
c ? ds4_gpu_tensor_const_obj(c) : nil,
};
for (uint32_t i = 0; i < 4; i++) {
if (tensors[i]) {
[enc setBuffer:tensors[i].buffer offset:(NSUInteger)tensors[i].offset atIndex:1 + i];
}
}
for (uint32_t i = 0; i < weight_count; i++) {
uint64_t inner = 0;
id<MTLBuffer> weight = ds4_gpu_wrap_model_exact_range(
weights[i].map,
weights[i].size,
weights[i].offset,
weights[i].bytes,
&inner);
if (!weight) {
ds4_gpu_end_compute_encoder(cb, enc);
if (owned) [cb commit];
return 0;
}
[enc setBuffer:weight offset:(NSUInteger)inner atIndex:5 + i];
}
const NSUInteger width = pipeline.threadExecutionWidth;
const NSUInteger max_threads = pipeline.maxTotalThreadsPerThreadgroup;
const NSUInteger threads = MIN(MAX(width, 1u), max_threads);
[enc dispatchThreads:MTLSizeMake(grid_x, grid_y, 1)
threadsPerThreadgroup:MTLSizeMake(threads, 1, 1)];
ds4_gpu_end_compute_encoder(cb, enc);
return owned ? ds4_gpu_finish_command_buffer(cb, 1, kernel) : 1;
}
uint32_t ds4_gpu_stream_expert_cache_configured_count(void) {
uint32_t budget = ds4_gpu_stream_expert_cache_configured_budget();
if (budget > DS4_METAL_STREAM_EXPERT_CACHE_MAX_ENTRIES) {