static_embeddings 1.5.6 → 1.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/ext/static_embeddings/se_alloc_stats.c +5 -6
- data/ext/static_embeddings/se_embed.c +4 -4
- data/ext/static_embeddings/se_f16.c +1 -1
- data/ext/static_embeddings/se_internal.h +14 -5
- data/ext/static_embeddings/se_tokenizer.c +9 -3
- data/ext/static_embeddings/se_topk.c +2 -3
- data/ext/static_embeddings/static_embeddings.c +70 -21
- data/lib/static_embeddings/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cbb2b16d03e01ba91c8c856890e98537ff81c4b4961a4d4172dc2e8a27fb46e3
|
|
4
|
+
data.tar.gz: d182451276da091e5410fa5dcbf93ec08e773bfa51cc6226f0c244db132e3656
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 54d96917d4a2fd738787ee12bd57a63f3793893a4abe3e59a9b860efe8508a895cb4d1cbd865f4f5692af1b2aa46eea21b17b55ed090b98a9af8df59946feadc
|
|
7
|
+
data.tar.gz: da73a4ead8792691b1e8433ecb7487f121e1dda88c61054e56f0f05b56c43f922a49643f1668da4c34be1258f654f134975cae5db875075f2a99e9bd2ea5256a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.8
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Cancellation flags shared by Ruby's unblock callback and native worker threads now use
|
|
8
|
+
atomic loads and stores, removing a C data race during interrupted embedding, tokenization,
|
|
9
|
+
and top-k operations.
|
|
10
|
+
|
|
11
|
+
## 1.5.7
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Model mappings are no longer closed while embedding, warmup, or token-ID
|
|
16
|
+
operations are using them without the GVL. `Model#close` raises
|
|
17
|
+
`StaticEmbeddings::Error` while such an operation is active.
|
|
18
|
+
- Tokenizer code-point writes now verify the capacity invariant after growth.
|
|
19
|
+
- Resolved Clang conversion warnings and formatting issues in the native code.
|
|
20
|
+
|
|
3
21
|
## 1.5.6
|
|
4
22
|
|
|
5
23
|
Multi-source WordPiece release. The native `.semb` v3 runtime is unchanged; new
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
#include <string.h>
|
|
6
6
|
|
|
7
7
|
static const char *const se_alloc_category_names[SE_ALLOC_CATEGORY_COUNT] = {
|
|
8
|
-
"unknown",
|
|
9
|
-
"
|
|
10
|
-
"topk_best", "topk_matrix_copy", "format_validate", "model_file"};
|
|
8
|
+
"unknown", "scratch", "batch_input", "batch_output", "batch_stats", "batch_index",
|
|
9
|
+
"token_ids", "topk_query", "topk_best", "topk_matrix_copy", "format_validate", "model_file"};
|
|
11
10
|
|
|
12
11
|
const char *se_alloc_category_name(se_alloc_category_t category) {
|
|
13
12
|
if ((unsigned)category >= SE_ALLOC_CATEGORY_COUNT)
|
|
@@ -176,7 +175,8 @@ void *se_alloc_stats_realloc(se_alloc_category_t category, void *ptr, size_t byt
|
|
|
176
175
|
if (old_header->h.magic != SE_ALLOC_STATS_MAGIC)
|
|
177
176
|
abort();
|
|
178
177
|
|
|
179
|
-
se_alloc_category_t old_category =
|
|
178
|
+
se_alloc_category_t old_category =
|
|
179
|
+
normalize_category((se_alloc_category_t)old_header->h.category);
|
|
180
180
|
size_t old_bytes = old_header->h.size;
|
|
181
181
|
se_alloc_header_t *new_header = (se_alloc_header_t *)realloc(old_header, total);
|
|
182
182
|
if (!new_header)
|
|
@@ -223,8 +223,7 @@ void se_alloc_stats_snapshot(se_alloc_stats_t out[SE_ALLOC_CATEGORY_COUNT]) {
|
|
|
223
223
|
for (size_t i = 0; i < SE_ALLOC_CATEGORY_COUNT; i++) {
|
|
224
224
|
out[i].current_bytes = atomic_load_size(&se_alloc_stats[i].current_bytes);
|
|
225
225
|
out[i].peak_bytes = atomic_load_size(&se_alloc_stats[i].peak_bytes);
|
|
226
|
-
out[i].total_allocated_bytes =
|
|
227
|
-
atomic_load_size(&se_alloc_stats[i].total_allocated_bytes);
|
|
226
|
+
out[i].total_allocated_bytes = atomic_load_size(&se_alloc_stats[i].total_allocated_bytes);
|
|
228
227
|
out[i].total_freed_bytes = atomic_load_size(&se_alloc_stats[i].total_freed_bytes);
|
|
229
228
|
out[i].alloc_count = atomic_load_size(&se_alloc_stats[i].alloc_count);
|
|
230
229
|
out[i].realloc_count = atomic_load_size(&se_alloc_stats[i].realloc_count);
|
|
@@ -119,7 +119,7 @@ void se_l2_normalize(float *vec, uint32_t dim) {
|
|
|
119
119
|
|
|
120
120
|
static se_status_t embed_ids_core(const se_model_t *model, se_scratch_t *sc, const uint32_t *ids,
|
|
121
121
|
size_t n, float *out, se_error_t *err,
|
|
122
|
-
|
|
122
|
+
se_cancel_flag_t *cancelled) {
|
|
123
123
|
const uint32_t dim = model->meta.dim;
|
|
124
124
|
float *acc = sc->acc;
|
|
125
125
|
memset(acc, 0, (size_t)dim * sizeof(float));
|
|
@@ -129,7 +129,7 @@ static se_status_t embed_ids_core(const se_model_t *model, se_scratch_t *sc, con
|
|
|
129
129
|
|
|
130
130
|
size_t used = 0;
|
|
131
131
|
for (size_t i = 0; i < n; i++) {
|
|
132
|
-
if (((i & 255u) == 0) && cancelled
|
|
132
|
+
if (((i & 255u) == 0) && se_cancel_requested(cancelled)) {
|
|
133
133
|
se_error_set(err, SE_ERR_INTERNAL, "operation cancelled");
|
|
134
134
|
return SE_ERR_INTERNAL;
|
|
135
135
|
}
|
|
@@ -179,7 +179,7 @@ static se_status_t embed_ids_core(const se_model_t *model, se_scratch_t *sc, con
|
|
|
179
179
|
|
|
180
180
|
se_status_t se_embed_ids(const se_model_t *model, se_scratch_t *sc, const uint32_t *ids,
|
|
181
181
|
size_t n_ids, float *out, se_token_stats_t *stats, se_error_t *err,
|
|
182
|
-
|
|
182
|
+
se_cancel_flag_t *cancelled) {
|
|
183
183
|
if (n_ids > UINT32_MAX) {
|
|
184
184
|
se_error_set(err, SE_ERR_OOM, "too many token ids");
|
|
185
185
|
return SE_ERR_OOM;
|
|
@@ -196,7 +196,7 @@ se_status_t se_embed_ids(const se_model_t *model, se_scratch_t *sc, const uint32
|
|
|
196
196
|
|
|
197
197
|
se_status_t se_embed_one(const se_model_t *model, se_scratch_t *sc, const uint8_t *input,
|
|
198
198
|
size_t input_len, uint32_t max_tokens, float *out, se_token_stats_t *stats,
|
|
199
|
-
se_error_t *err,
|
|
199
|
+
se_error_t *err, se_cancel_flag_t *cancelled) {
|
|
200
200
|
se_status_t rc = se_tokenize(model, sc, input, input_len, max_tokens, SE_TOKEN_LIMIT_USABLE,
|
|
201
201
|
stats, err, cancelled);
|
|
202
202
|
if (rc != SE_OK)
|
|
@@ -35,7 +35,7 @@ static void write_u16le(uint8_t *dst, uint16_t v) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
static uint16_t read_u16le(const uint8_t *src) {
|
|
38
|
-
return (uint16_t)src[0] | ((uint16_t)src[1] << 8);
|
|
38
|
+
return (uint16_t)((uint16_t)src[0] | ((uint16_t)src[1] << 8));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
uint16_t se_float_to_f16_bits(float value) {
|
|
@@ -3,9 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
#include <stddef.h>
|
|
5
5
|
#include <stdint.h>
|
|
6
|
-
#include <signal.h>
|
|
7
6
|
#include <limits.h>
|
|
8
7
|
|
|
8
|
+
typedef int se_cancel_flag_t;
|
|
9
|
+
|
|
10
|
+
static inline int se_cancel_requested(const se_cancel_flag_t *flag) {
|
|
11
|
+
return flag && __atomic_load_n(flag, __ATOMIC_RELAXED);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static inline void se_cancel_request(se_cancel_flag_t *flag) {
|
|
15
|
+
__atomic_store_n(flag, 1, __ATOMIC_RELAXED);
|
|
16
|
+
}
|
|
17
|
+
|
|
9
18
|
#define SE_MAGIC "SEMBv1\0\0"
|
|
10
19
|
#define SE_MAGIC_LEN 8
|
|
11
20
|
#define SE_FORMAT_VERSION 3u
|
|
@@ -277,7 +286,7 @@ typedef struct {
|
|
|
277
286
|
float *best_score;
|
|
278
287
|
int cosine;
|
|
279
288
|
float inv_query_norm;
|
|
280
|
-
|
|
289
|
+
se_cancel_flag_t cancelled;
|
|
281
290
|
} se_topk_job_t;
|
|
282
291
|
|
|
283
292
|
SE_STATIC_ASSERT(sizeof(se_vocab_slot_t) == 16, vocab_slot_size);
|
|
@@ -415,14 +424,14 @@ typedef enum { SE_TOKEN_LIMIT_RAW = 0, SE_TOKEN_LIMIT_USABLE = 1 } se_token_limi
|
|
|
415
424
|
|
|
416
425
|
se_status_t se_tokenize(const se_model_t *model, se_scratch_t *scratch, const uint8_t *input,
|
|
417
426
|
size_t input_len, uint32_t max_tokens, se_token_limit_t limit_mode,
|
|
418
|
-
se_token_stats_t *stats, se_error_t *err,
|
|
427
|
+
se_token_stats_t *stats, se_error_t *err, se_cancel_flag_t *cancelled);
|
|
419
428
|
|
|
420
429
|
se_status_t se_embed_one(const se_model_t *model, se_scratch_t *scratch, const uint8_t *input,
|
|
421
430
|
size_t input_len, uint32_t max_tokens, float *out, se_token_stats_t *stats,
|
|
422
|
-
se_error_t *err,
|
|
431
|
+
se_error_t *err, se_cancel_flag_t *cancelled);
|
|
423
432
|
se_status_t se_embed_ids(const se_model_t *model, se_scratch_t *scratch, const uint32_t *ids,
|
|
424
433
|
size_t n_ids, float *out, se_token_stats_t *stats, se_error_t *err,
|
|
425
|
-
|
|
434
|
+
se_cancel_flag_t *cancelled);
|
|
426
435
|
|
|
427
436
|
void se_l2_normalize(float *vec, uint32_t dim);
|
|
428
437
|
size_t se_model_warmup(const se_model_t *model);
|
|
@@ -495,11 +495,11 @@ typedef struct {
|
|
|
495
495
|
int segment_ascii;
|
|
496
496
|
se_token_stats_t *stats;
|
|
497
497
|
se_error_t *err;
|
|
498
|
-
|
|
498
|
+
se_cancel_flag_t *cancelled;
|
|
499
499
|
} token_state_t;
|
|
500
500
|
|
|
501
501
|
static int token_cancelled(const token_state_t *st) {
|
|
502
|
-
return st->cancelled
|
|
502
|
+
return se_cancel_requested(st->cancelled);
|
|
503
503
|
}
|
|
504
504
|
|
|
505
505
|
static se_status_t oom(token_state_t *st, const char *where) {
|
|
@@ -512,6 +512,8 @@ static int append_segment_cp(token_state_t *st, uint32_t cp) {
|
|
|
512
512
|
st->segment_ascii = 0;
|
|
513
513
|
if (!grow_u32(&st->scratch->cps, &st->scratch->cps_cap, st->segment_len + 1))
|
|
514
514
|
return 0;
|
|
515
|
+
if (st->segment_len >= st->scratch->cps_cap)
|
|
516
|
+
return 0;
|
|
515
517
|
st->scratch->cps[st->segment_len++] = cp;
|
|
516
518
|
return 1;
|
|
517
519
|
}
|
|
@@ -906,6 +908,10 @@ static se_status_t tokenize_ascii_run(token_state_t *st, const uint8_t *input, s
|
|
|
906
908
|
return oom(st, "building token segment");
|
|
907
909
|
}
|
|
908
910
|
}
|
|
911
|
+
if (st->segment_len >= sc->cps_cap) {
|
|
912
|
+
*ip = i;
|
|
913
|
+
return oom(st, "building token segment");
|
|
914
|
+
}
|
|
909
915
|
sc->cps[st->segment_len++] =
|
|
910
916
|
(lc && b >= 'A' && b <= 'Z') ? (uint32_t)(b + 32u) : (uint32_t)b;
|
|
911
917
|
i++;
|
|
@@ -948,7 +954,7 @@ static se_status_t tokenize_ascii_run(token_state_t *st, const uint8_t *input, s
|
|
|
948
954
|
se_status_t se_tokenize(const se_model_t *model, se_scratch_t *sc, const uint8_t *input,
|
|
949
955
|
size_t input_len, uint32_t max_tokens, se_token_limit_t limit_mode,
|
|
950
956
|
se_token_stats_t *stats, se_error_t *err,
|
|
951
|
-
|
|
957
|
+
se_cancel_flag_t *cancelled) {
|
|
952
958
|
memset(stats, 0, sizeof(*stats));
|
|
953
959
|
|
|
954
960
|
token_state_t st;
|
|
@@ -73,8 +73,7 @@ float se_dot_product_f32(const float *q, const float *row, size_t dim) {
|
|
|
73
73
|
return dot;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
float se_dot_and_row_sq_f32(const float *q, const float *row, size_t dim,
|
|
77
|
-
float *row_sq_out) {
|
|
76
|
+
float se_dot_and_row_sq_f32(const float *q, const float *row, size_t dim, float *row_sq_out) {
|
|
78
77
|
size_t j = 0;
|
|
79
78
|
#if defined(SE_HAVE_NEON)
|
|
80
79
|
float32x4_t d0 = vdupq_n_f32(0.0f);
|
|
@@ -196,7 +195,7 @@ static float cosine_score(float dot, float row_sq, float inv_query_norm) {
|
|
|
196
195
|
void *se_topk_execute(void *arg) {
|
|
197
196
|
se_topk_job_t *job = (se_topk_job_t *)arg;
|
|
198
197
|
for (size_t r = 0; r < job->rows; r++) {
|
|
199
|
-
if ((r & 1023u) == 0 && job->cancelled)
|
|
198
|
+
if ((r & 1023u) == 0 && se_cancel_requested(&job->cancelled))
|
|
200
199
|
return NULL;
|
|
201
200
|
float score;
|
|
202
201
|
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
#include <float.h>
|
|
10
10
|
#include <limits.h>
|
|
11
11
|
#include <math.h>
|
|
12
|
-
#include <signal.h>
|
|
13
12
|
#include <stdint.h>
|
|
14
13
|
#include <stdio.h>
|
|
15
14
|
#include <stdlib.h>
|
|
@@ -93,6 +92,7 @@ RUBY_FUNC_EXPORTED void Init_static_embeddings(void);
|
|
|
93
92
|
typedef struct {
|
|
94
93
|
se_model_t model;
|
|
95
94
|
int open;
|
|
95
|
+
unsigned int active_ops;
|
|
96
96
|
} model_wrapper_t;
|
|
97
97
|
|
|
98
98
|
static void model_free(void *ptr) {
|
|
@@ -177,7 +177,7 @@ static void check_text_encoding_mode(VALUE str, long index, se_encoding_validati
|
|
|
177
177
|
rb_enc_name(enc));
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
int cr = ENC_CODERANGE(str);
|
|
180
|
+
int cr = (int)ENC_CODERANGE(str);
|
|
181
181
|
if (cr == ENC_CODERANGE_UNKNOWN) {
|
|
182
182
|
if (mode == SE_VALIDATE_ENCODING_PREFIX)
|
|
183
183
|
return;
|
|
@@ -216,6 +216,7 @@ typedef struct {
|
|
|
216
216
|
|
|
217
217
|
typedef struct {
|
|
218
218
|
const se_model_t *model;
|
|
219
|
+
model_wrapper_t *owner;
|
|
219
220
|
batch_input_t input;
|
|
220
221
|
uint32_t max_tokens;
|
|
221
222
|
float *out;
|
|
@@ -224,10 +225,12 @@ typedef struct {
|
|
|
224
225
|
size_t next_index;
|
|
225
226
|
int failed;
|
|
226
227
|
size_t failed_index;
|
|
227
|
-
|
|
228
|
+
se_cancel_flag_t cancelled;
|
|
228
229
|
se_error_t error;
|
|
229
230
|
} batch_job_t;
|
|
230
231
|
|
|
232
|
+
static void run_job(batch_job_t *job, size_t total_bytes);
|
|
233
|
+
|
|
231
234
|
static void job_fail(batch_job_t *job, se_error_t err, size_t index) {
|
|
232
235
|
if (job->failed)
|
|
233
236
|
return;
|
|
@@ -240,7 +243,7 @@ static void batch_worker_run(batch_job_t *job, se_scratch_t *scratch) {
|
|
|
240
243
|
const uint32_t dim = job->model->meta.dim;
|
|
241
244
|
|
|
242
245
|
for (;;) {
|
|
243
|
-
if (job->cancelled) {
|
|
246
|
+
if (se_cancel_requested(&job->cancelled)) {
|
|
244
247
|
se_error_set(&job->error, SE_ERR_INTERNAL, "operation cancelled");
|
|
245
248
|
job->failed = 1;
|
|
246
249
|
return;
|
|
@@ -289,7 +292,7 @@ static void *batch_execute(void *arg) {
|
|
|
289
292
|
static void unblock_cancel(void *arg) {
|
|
290
293
|
batch_job_t *job = (batch_job_t *)arg;
|
|
291
294
|
if (job)
|
|
292
|
-
job->cancelled
|
|
295
|
+
se_cancel_request(&job->cancelled);
|
|
293
296
|
}
|
|
294
297
|
|
|
295
298
|
static VALUE current_fiber_scheduler(void) {
|
|
@@ -354,13 +357,28 @@ static VALUE fiber_worker_ensure(VALUE wrapper) {
|
|
|
354
357
|
fiber_worker_t *w;
|
|
355
358
|
TypedData_Get_Struct(wrapper, fiber_worker_t, &fiber_worker_type, w);
|
|
356
359
|
if (!NIL_P(w->thread)) {
|
|
357
|
-
w->job->cancelled
|
|
360
|
+
se_cancel_request(&w->job->cancelled);
|
|
358
361
|
rb_funcall(w->thread, id_kill, 0);
|
|
359
362
|
rb_funcall(w->thread, id_join, 0);
|
|
360
363
|
}
|
|
361
364
|
return Qnil;
|
|
362
365
|
}
|
|
363
366
|
|
|
367
|
+
static VALUE run_job_body(VALUE arg) {
|
|
368
|
+
batch_job_t *job = (batch_job_t *)(uintptr_t)arg;
|
|
369
|
+
size_t total_bytes = 0;
|
|
370
|
+
for (size_t i = 0; i < job->input.count; i++)
|
|
371
|
+
total_bytes += job->input.lengths[i];
|
|
372
|
+
run_job(job, total_bytes);
|
|
373
|
+
return Qnil;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
static VALUE run_job_ensure(VALUE arg) {
|
|
377
|
+
batch_job_t *job = (batch_job_t *)(uintptr_t)arg;
|
|
378
|
+
job->owner->active_ops--;
|
|
379
|
+
return Qnil;
|
|
380
|
+
}
|
|
381
|
+
|
|
364
382
|
static void run_job(batch_job_t *job, size_t total_bytes) {
|
|
365
383
|
VALUE scheduler = current_fiber_scheduler();
|
|
366
384
|
|
|
@@ -386,11 +404,8 @@ static void run_job(batch_job_t *job, size_t total_bytes) {
|
|
|
386
404
|
|
|
387
405
|
static VALUE protected_run_job(VALUE arg) {
|
|
388
406
|
batch_job_t *job = (batch_job_t *)(uintptr_t)arg;
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
total_bytes += job->input.lengths[i];
|
|
392
|
-
run_job(job, total_bytes);
|
|
393
|
-
return Qnil;
|
|
407
|
+
job->owner->active_ops++;
|
|
408
|
+
return rb_ensure(run_job_body, arg, run_job_ensure, arg);
|
|
394
409
|
}
|
|
395
410
|
|
|
396
411
|
static VALUE model_alloc(VALUE klass) {
|
|
@@ -422,6 +437,8 @@ static VALUE model_close(VALUE self) {
|
|
|
422
437
|
model_wrapper_t *w;
|
|
423
438
|
TypedData_Get_Struct(self, model_wrapper_t, &model_type, w);
|
|
424
439
|
if (w->open) {
|
|
440
|
+
if (w->active_ops != 0)
|
|
441
|
+
rb_raise(eError, "model is busy with an active operation");
|
|
425
442
|
se_model_close(&w->model);
|
|
426
443
|
w->open = 0;
|
|
427
444
|
}
|
|
@@ -474,18 +491,40 @@ typedef struct {
|
|
|
474
491
|
size_t pages;
|
|
475
492
|
} warmup_job_t;
|
|
476
493
|
|
|
494
|
+
typedef struct {
|
|
495
|
+
VALUE self;
|
|
496
|
+
model_wrapper_t *owner;
|
|
497
|
+
warmup_job_t job;
|
|
498
|
+
} warmup_run_t;
|
|
499
|
+
|
|
477
500
|
static void *warmup_execute(void *arg) {
|
|
478
501
|
warmup_job_t *job = (warmup_job_t *)arg;
|
|
479
502
|
job->pages = se_model_warmup(job->model);
|
|
480
503
|
return NULL;
|
|
481
504
|
}
|
|
482
505
|
|
|
506
|
+
static VALUE warmup_body(VALUE arg) {
|
|
507
|
+
warmup_run_t *run = (warmup_run_t *)(uintptr_t)arg;
|
|
508
|
+
rb_thread_call_without_gvl(warmup_execute, &run->job, NULL, NULL);
|
|
509
|
+
RB_GC_GUARD(run->self);
|
|
510
|
+
return Qnil;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
static VALUE warmup_ensure(VALUE arg) {
|
|
514
|
+
warmup_run_t *run = (warmup_run_t *)(uintptr_t)arg;
|
|
515
|
+
run->owner->active_ops--;
|
|
516
|
+
return Qnil;
|
|
517
|
+
}
|
|
518
|
+
|
|
483
519
|
static VALUE model_warmup(VALUE self) {
|
|
484
520
|
model_wrapper_t *w = get_model(self);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
521
|
+
warmup_run_t run;
|
|
522
|
+
run.self = self;
|
|
523
|
+
run.owner = w;
|
|
524
|
+
run.job.model = &w->model;
|
|
525
|
+
run.job.pages = 0;
|
|
526
|
+
w->active_ops++;
|
|
527
|
+
rb_ensure(warmup_body, (VALUE)(uintptr_t)&run, warmup_ensure, (VALUE)(uintptr_t)&run);
|
|
489
528
|
RB_GC_GUARD(self);
|
|
490
529
|
return self;
|
|
491
530
|
}
|
|
@@ -829,6 +868,7 @@ static VALUE embed_texts_internal(VALUE self, VALUE texts, int is_array, size_t
|
|
|
829
868
|
batch_job_t job;
|
|
830
869
|
memset(&job, 0, sizeof(job));
|
|
831
870
|
job.model = model;
|
|
871
|
+
job.owner = w;
|
|
832
872
|
job.max_tokens = max_tokens;
|
|
833
873
|
job.out = run.out;
|
|
834
874
|
job.stats = run.stats;
|
|
@@ -844,7 +884,7 @@ static VALUE embed_texts_internal(VALUE self, VALUE texts, int is_array, size_t
|
|
|
844
884
|
int state = 0;
|
|
845
885
|
rb_protect(protected_run_job, (VALUE)(uintptr_t)&job, &state);
|
|
846
886
|
if (state) {
|
|
847
|
-
job.cancelled
|
|
887
|
+
se_cancel_request(&job.cancelled);
|
|
848
888
|
free_input(&job.input);
|
|
849
889
|
embed_run_free(&run);
|
|
850
890
|
rb_jump_tag(state);
|
|
@@ -1110,12 +1150,13 @@ typedef struct {
|
|
|
1110
1150
|
size_t n_ids;
|
|
1111
1151
|
float *out;
|
|
1112
1152
|
se_token_stats_t stats;
|
|
1113
|
-
|
|
1153
|
+
se_cancel_flag_t cancelled;
|
|
1114
1154
|
se_error_t error;
|
|
1115
1155
|
} ids_job_t;
|
|
1116
1156
|
|
|
1117
1157
|
typedef struct {
|
|
1118
1158
|
VALUE ids_value;
|
|
1159
|
+
model_wrapper_t *owner;
|
|
1119
1160
|
const se_model_t *model;
|
|
1120
1161
|
uint32_t max_tokens;
|
|
1121
1162
|
uint32_t *ids;
|
|
@@ -1126,6 +1167,7 @@ typedef struct {
|
|
|
1126
1167
|
se_token_stats_t *stats_out;
|
|
1127
1168
|
se_token_stats_t stats;
|
|
1128
1169
|
int truncated;
|
|
1170
|
+
int active;
|
|
1129
1171
|
} ids_run_t;
|
|
1130
1172
|
|
|
1131
1173
|
typedef struct {
|
|
@@ -1157,7 +1199,7 @@ static void *ids_execute(void *arg) {
|
|
|
1157
1199
|
static void ids_unblock_cancel(void *arg) {
|
|
1158
1200
|
ids_job_t *job = (ids_job_t *)arg;
|
|
1159
1201
|
if (job)
|
|
1160
|
-
job->cancelled
|
|
1202
|
+
se_cancel_request(&job->cancelled);
|
|
1161
1203
|
}
|
|
1162
1204
|
|
|
1163
1205
|
static VALUE embed_token_ids_body(VALUE arg) {
|
|
@@ -1197,9 +1239,13 @@ static VALUE embed_token_ids_body(VALUE arg) {
|
|
|
1197
1239
|
se_error_clear(&job.error);
|
|
1198
1240
|
|
|
1199
1241
|
if (run->n >= SE_IDS_GVL_UNLOCK_THRESHOLD) {
|
|
1242
|
+
run->owner->active_ops++;
|
|
1243
|
+
run->active = 1;
|
|
1200
1244
|
rb_thread_call_without_gvl(ids_execute, &job, ids_unblock_cancel, &job);
|
|
1245
|
+
run->owner->active_ops--;
|
|
1246
|
+
run->active = 0;
|
|
1201
1247
|
rb_thread_check_ints();
|
|
1202
|
-
if (job.cancelled)
|
|
1248
|
+
if (se_cancel_requested(&job.cancelled))
|
|
1203
1249
|
rb_raise(rb_eInterrupt, "operation cancelled");
|
|
1204
1250
|
} else {
|
|
1205
1251
|
ids_execute(&job);
|
|
@@ -1225,6 +1271,8 @@ static VALUE embed_token_ids_body(VALUE arg) {
|
|
|
1225
1271
|
|
|
1226
1272
|
static VALUE embed_token_ids_ensure(VALUE arg) {
|
|
1227
1273
|
ids_run_t *run = (ids_run_t *)(uintptr_t)arg;
|
|
1274
|
+
if (run->active)
|
|
1275
|
+
run->owner->active_ops--;
|
|
1228
1276
|
se_free(run->ids);
|
|
1229
1277
|
se_free(run->out);
|
|
1230
1278
|
run->ids = NULL;
|
|
@@ -1280,6 +1328,7 @@ static VALUE embed_token_ids_value(VALUE self, VALUE ids_value, VALUE max_tokens
|
|
|
1280
1328
|
ids_run_t run;
|
|
1281
1329
|
memset(&run, 0, sizeof(run));
|
|
1282
1330
|
run.ids_value = ids_value;
|
|
1331
|
+
run.owner = w;
|
|
1283
1332
|
run.model = &w->model;
|
|
1284
1333
|
run.max_tokens = max_tokens;
|
|
1285
1334
|
run.n = n;
|
|
@@ -1346,7 +1395,7 @@ static int ptr_is_float_aligned(const void *ptr) {
|
|
|
1346
1395
|
static void topk_unblock_cancel(void *arg) {
|
|
1347
1396
|
se_topk_job_t *job = (se_topk_job_t *)arg;
|
|
1348
1397
|
if (job)
|
|
1349
|
-
job->cancelled
|
|
1398
|
+
se_cancel_request(&job->cancelled);
|
|
1350
1399
|
}
|
|
1351
1400
|
|
|
1352
1401
|
static VALUE topk_body(VALUE arg) {
|
|
@@ -1375,7 +1424,7 @@ static VALUE topk_body(VALUE arg) {
|
|
|
1375
1424
|
rb_thread_check_ints();
|
|
1376
1425
|
}
|
|
1377
1426
|
|
|
1378
|
-
if (run->job.cancelled)
|
|
1427
|
+
if (se_cancel_requested(&run->job.cancelled))
|
|
1379
1428
|
rb_raise(rb_eInterrupt, "operation cancelled");
|
|
1380
1429
|
|
|
1381
1430
|
VALUE result = rb_ary_new_capa(run->job.k);
|