Align DeepSeek and GLM execution with DS4
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Metal/Metal.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <time.h>
|
||||
#include "ds4_gpu.h"
|
||||
|
||||
/* Shared optional UI/headless probe. Process placement matters: a separate
|
||||
* queue in the model process is not a separate-process scheduling test. */
|
||||
static id<MTLDevice> g_canary_device;
|
||||
static id<MTLCommandQueue> g_canary_queue;
|
||||
static id<MTLBuffer> g_canary_buffer;
|
||||
|
||||
static double ds4_monotonic_seconds(void) {
|
||||
struct timespec time;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) return 0.0;
|
||||
return (double)time.tv_sec + (double)time.tv_nsec / 1000000000.0;
|
||||
}
|
||||
|
||||
int ds4_gpu_canary_probe(ds4_gpu_canary_sample *sample) {
|
||||
if (!sample) return 0;
|
||||
sample->scheduled_seconds = 0.0;
|
||||
sample->completed_seconds = 0.0;
|
||||
sample->gpu_wait_seconds = -1.0;
|
||||
sample->gpu_interval_seconds = -1.0;
|
||||
sample->host_return_seconds = -1.0;
|
||||
@autoreleasepool {
|
||||
if (!g_canary_device) g_canary_device = MTLCreateSystemDefaultDevice();
|
||||
if (!g_canary_queue && g_canary_device) {
|
||||
g_canary_queue = [g_canary_device newCommandQueue];
|
||||
}
|
||||
if (!g_canary_buffer && g_canary_device) {
|
||||
g_canary_buffer = [g_canary_device newBufferWithLength:4096
|
||||
options:MTLResourceStorageModeShared];
|
||||
}
|
||||
if (!g_canary_queue || !g_canary_buffer) return 0;
|
||||
|
||||
id<MTLCommandBuffer> cb = [g_canary_queue commandBuffer];
|
||||
id<MTLBlitCommandEncoder> blit = [cb blitCommandEncoder];
|
||||
if (!cb || !blit) return 0;
|
||||
[blit fillBuffer:g_canary_buffer range:NSMakeRange(0, 4096) value:0];
|
||||
[blit endEncoding];
|
||||
mach_timebase_info_data_t timebase;
|
||||
if (mach_timebase_info(&timebase) != KERN_SUCCESS || !timebase.denom) return 0;
|
||||
const double scale = (double)timebase.numer / timebase.denom / 1e9;
|
||||
const double started = ds4_monotonic_seconds();
|
||||
const double mach_started = (double)mach_absolute_time() * scale;
|
||||
[cb commit];
|
||||
[cb waitUntilScheduled];
|
||||
sample->scheduled_seconds = ds4_monotonic_seconds() - started;
|
||||
[cb waitUntilCompleted];
|
||||
const double mach_returned = (double)mach_absolute_time() * scale;
|
||||
sample->completed_seconds = ds4_monotonic_seconds() - started;
|
||||
// Metal GPU times use system mach time, unlike CLOCK_MONOTONIC on
|
||||
// macOS. Read only after completion; unavailable timestamps stay -1.
|
||||
const double gpu_start = cb.GPUStartTime;
|
||||
const double gpu_end = cb.GPUEndTime;
|
||||
if (gpu_start > 0.0 && gpu_start >= mach_started &&
|
||||
gpu_end >= gpu_start && mach_returned >= gpu_end) {
|
||||
sample->gpu_wait_seconds = gpu_start - mach_started;
|
||||
// Includes GPU scheduling/preemption, not exclusive busy time.
|
||||
sample->gpu_interval_seconds = gpu_end - gpu_start;
|
||||
sample->host_return_seconds = mach_returned - gpu_end;
|
||||
}
|
||||
return cb.status == MTLCommandBufferStatusCompleted;
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,9 @@ void ds4_gpu_busy_stats_get(ds4_gpu_busy_stats *stats);
|
||||
typedef struct {
|
||||
double scheduled_seconds;
|
||||
double completed_seconds;
|
||||
double gpu_wait_seconds;
|
||||
double gpu_interval_seconds;
|
||||
double host_return_seconds;
|
||||
} ds4_gpu_canary_sample;
|
||||
int ds4_gpu_canary_probe(ds4_gpu_canary_sample *sample);
|
||||
#ifdef __APPLE__
|
||||
|
||||
@@ -1201,48 +1201,6 @@ static void ds4_gpu_busy_stats_record(id<MTLCommandBuffer> cb, uint64_t epoch) {
|
||||
}
|
||||
}
|
||||
|
||||
/* A separate queue used by the headless evaluator's supervisor process. The
|
||||
* tiny blit measures whether another process can still schedule UI-sized GPU
|
||||
* work while the model owns its own Metal queue. */
|
||||
static id<MTLDevice> g_canary_device;
|
||||
static id<MTLCommandQueue> g_canary_queue;
|
||||
static id<MTLBuffer> g_canary_buffer;
|
||||
|
||||
static double ds4_monotonic_seconds(void) {
|
||||
struct timespec time;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) return 0.0;
|
||||
return (double)time.tv_sec + (double)time.tv_nsec / 1000000000.0;
|
||||
}
|
||||
|
||||
int ds4_gpu_canary_probe(ds4_gpu_canary_sample *sample) {
|
||||
if (!sample) return 0;
|
||||
sample->scheduled_seconds = 0.0;
|
||||
sample->completed_seconds = 0.0;
|
||||
@autoreleasepool {
|
||||
if (!g_canary_device) g_canary_device = MTLCreateSystemDefaultDevice();
|
||||
if (!g_canary_queue && g_canary_device) {
|
||||
g_canary_queue = [g_canary_device newCommandQueue];
|
||||
}
|
||||
if (!g_canary_buffer && g_canary_device) {
|
||||
g_canary_buffer = [g_canary_device newBufferWithLength:4096
|
||||
options:MTLResourceStorageModeShared];
|
||||
}
|
||||
if (!g_canary_queue || !g_canary_buffer) return 0;
|
||||
|
||||
id<MTLCommandBuffer> cb = [g_canary_queue commandBuffer];
|
||||
id<MTLBlitCommandEncoder> blit = [cb blitCommandEncoder];
|
||||
if (!cb || !blit) return 0;
|
||||
[blit fillBuffer:g_canary_buffer range:NSMakeRange(0, 4096) value:0];
|
||||
[blit endEncoding];
|
||||
const double started = ds4_monotonic_seconds();
|
||||
ds4_gpu_commit_command_buffer(cb);
|
||||
[cb waitUntilScheduled];
|
||||
sample->scheduled_seconds = ds4_monotonic_seconds() - started;
|
||||
[cb waitUntilCompleted];
|
||||
sample->completed_seconds = ds4_monotonic_seconds() - started;
|
||||
return cb.status == MTLCommandBufferStatusCompleted;
|
||||
}
|
||||
}
|
||||
|
||||
/* A failed command buffer can leave a cross-threadgroup arrival counter at an
|
||||
* arbitrary partial value. Drop cached ownership instead of CPU-resetting
|
||||
|
||||
Reference in New Issue
Block a user