static_embeddings 1.5.6 → 1.5.7
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 +10 -0
- data/ext/static_embeddings/se_alloc_stats.c +5 -6
- data/ext/static_embeddings/se_f16.c +1 -1
- data/ext/static_embeddings/se_tokenizer.c +6 -0
- data/ext/static_embeddings/se_topk.c +1 -2
- data/ext/static_embeddings/static_embeddings.c +60 -10
- 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: a8e174dd93ba3b3e9ee25047fd28ea5ba980d096a4922c0b8325c366208bff65
|
|
4
|
+
data.tar.gz: 741e0cc35791d9a335c82a05aed18e3388232828824168ff59ed1751c281e8a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 58462ed4c203fb657630d092e1a4aa85857e5d44106bb97feae26f12579fc4b6d88d20632e462624ad0cb93e1d0d0e735f91ee12aaec80b637d29b313e6dc53d
|
|
7
|
+
data.tar.gz: 80e9897969dfe6aace3d851f1a11ffb6610b628cddc35239301a676b2ce32d97d1a8a614ae6dca0526703e61d6d813af89965d0906c593392e66cdd25f7e16da
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.7
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Model mappings are no longer closed while embedding, warmup, or token-ID
|
|
8
|
+
operations are using them without the GVL. `Model#close` raises
|
|
9
|
+
`StaticEmbeddings::Error` while such an operation is active.
|
|
10
|
+
- Tokenizer code-point writes now verify the capacity invariant after growth.
|
|
11
|
+
- Resolved Clang conversion warnings and formatting issues in the native code.
|
|
12
|
+
|
|
3
13
|
## 1.5.6
|
|
4
14
|
|
|
5
15
|
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);
|
|
@@ -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) {
|
|
@@ -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++;
|
|
@@ -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);
|
|
@@ -93,6 +93,7 @@ RUBY_FUNC_EXPORTED void Init_static_embeddings(void);
|
|
|
93
93
|
typedef struct {
|
|
94
94
|
se_model_t model;
|
|
95
95
|
int open;
|
|
96
|
+
unsigned int active_ops;
|
|
96
97
|
} model_wrapper_t;
|
|
97
98
|
|
|
98
99
|
static void model_free(void *ptr) {
|
|
@@ -177,7 +178,7 @@ static void check_text_encoding_mode(VALUE str, long index, se_encoding_validati
|
|
|
177
178
|
rb_enc_name(enc));
|
|
178
179
|
}
|
|
179
180
|
|
|
180
|
-
int cr = ENC_CODERANGE(str);
|
|
181
|
+
int cr = (int)ENC_CODERANGE(str);
|
|
181
182
|
if (cr == ENC_CODERANGE_UNKNOWN) {
|
|
182
183
|
if (mode == SE_VALIDATE_ENCODING_PREFIX)
|
|
183
184
|
return;
|
|
@@ -216,6 +217,7 @@ typedef struct {
|
|
|
216
217
|
|
|
217
218
|
typedef struct {
|
|
218
219
|
const se_model_t *model;
|
|
220
|
+
model_wrapper_t *owner;
|
|
219
221
|
batch_input_t input;
|
|
220
222
|
uint32_t max_tokens;
|
|
221
223
|
float *out;
|
|
@@ -228,6 +230,8 @@ typedef struct {
|
|
|
228
230
|
se_error_t error;
|
|
229
231
|
} batch_job_t;
|
|
230
232
|
|
|
233
|
+
static void run_job(batch_job_t *job, size_t total_bytes);
|
|
234
|
+
|
|
231
235
|
static void job_fail(batch_job_t *job, se_error_t err, size_t index) {
|
|
232
236
|
if (job->failed)
|
|
233
237
|
return;
|
|
@@ -361,6 +365,21 @@ static VALUE fiber_worker_ensure(VALUE wrapper) {
|
|
|
361
365
|
return Qnil;
|
|
362
366
|
}
|
|
363
367
|
|
|
368
|
+
static VALUE run_job_body(VALUE arg) {
|
|
369
|
+
batch_job_t *job = (batch_job_t *)(uintptr_t)arg;
|
|
370
|
+
size_t total_bytes = 0;
|
|
371
|
+
for (size_t i = 0; i < job->input.count; i++)
|
|
372
|
+
total_bytes += job->input.lengths[i];
|
|
373
|
+
run_job(job, total_bytes);
|
|
374
|
+
return Qnil;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
static VALUE run_job_ensure(VALUE arg) {
|
|
378
|
+
batch_job_t *job = (batch_job_t *)(uintptr_t)arg;
|
|
379
|
+
job->owner->active_ops--;
|
|
380
|
+
return Qnil;
|
|
381
|
+
}
|
|
382
|
+
|
|
364
383
|
static void run_job(batch_job_t *job, size_t total_bytes) {
|
|
365
384
|
VALUE scheduler = current_fiber_scheduler();
|
|
366
385
|
|
|
@@ -386,11 +405,8 @@ static void run_job(batch_job_t *job, size_t total_bytes) {
|
|
|
386
405
|
|
|
387
406
|
static VALUE protected_run_job(VALUE arg) {
|
|
388
407
|
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;
|
|
408
|
+
job->owner->active_ops++;
|
|
409
|
+
return rb_ensure(run_job_body, arg, run_job_ensure, arg);
|
|
394
410
|
}
|
|
395
411
|
|
|
396
412
|
static VALUE model_alloc(VALUE klass) {
|
|
@@ -422,6 +438,8 @@ static VALUE model_close(VALUE self) {
|
|
|
422
438
|
model_wrapper_t *w;
|
|
423
439
|
TypedData_Get_Struct(self, model_wrapper_t, &model_type, w);
|
|
424
440
|
if (w->open) {
|
|
441
|
+
if (w->active_ops != 0)
|
|
442
|
+
rb_raise(eError, "model is busy with an active operation");
|
|
425
443
|
se_model_close(&w->model);
|
|
426
444
|
w->open = 0;
|
|
427
445
|
}
|
|
@@ -474,18 +492,40 @@ typedef struct {
|
|
|
474
492
|
size_t pages;
|
|
475
493
|
} warmup_job_t;
|
|
476
494
|
|
|
495
|
+
typedef struct {
|
|
496
|
+
VALUE self;
|
|
497
|
+
model_wrapper_t *owner;
|
|
498
|
+
warmup_job_t job;
|
|
499
|
+
} warmup_run_t;
|
|
500
|
+
|
|
477
501
|
static void *warmup_execute(void *arg) {
|
|
478
502
|
warmup_job_t *job = (warmup_job_t *)arg;
|
|
479
503
|
job->pages = se_model_warmup(job->model);
|
|
480
504
|
return NULL;
|
|
481
505
|
}
|
|
482
506
|
|
|
507
|
+
static VALUE warmup_body(VALUE arg) {
|
|
508
|
+
warmup_run_t *run = (warmup_run_t *)(uintptr_t)arg;
|
|
509
|
+
rb_thread_call_without_gvl(warmup_execute, &run->job, NULL, NULL);
|
|
510
|
+
RB_GC_GUARD(run->self);
|
|
511
|
+
return Qnil;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
static VALUE warmup_ensure(VALUE arg) {
|
|
515
|
+
warmup_run_t *run = (warmup_run_t *)(uintptr_t)arg;
|
|
516
|
+
run->owner->active_ops--;
|
|
517
|
+
return Qnil;
|
|
518
|
+
}
|
|
519
|
+
|
|
483
520
|
static VALUE model_warmup(VALUE self) {
|
|
484
521
|
model_wrapper_t *w = get_model(self);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
522
|
+
warmup_run_t run;
|
|
523
|
+
run.self = self;
|
|
524
|
+
run.owner = w;
|
|
525
|
+
run.job.model = &w->model;
|
|
526
|
+
run.job.pages = 0;
|
|
527
|
+
w->active_ops++;
|
|
528
|
+
rb_ensure(warmup_body, (VALUE)(uintptr_t)&run, warmup_ensure, (VALUE)(uintptr_t)&run);
|
|
489
529
|
RB_GC_GUARD(self);
|
|
490
530
|
return self;
|
|
491
531
|
}
|
|
@@ -829,6 +869,7 @@ static VALUE embed_texts_internal(VALUE self, VALUE texts, int is_array, size_t
|
|
|
829
869
|
batch_job_t job;
|
|
830
870
|
memset(&job, 0, sizeof(job));
|
|
831
871
|
job.model = model;
|
|
872
|
+
job.owner = w;
|
|
832
873
|
job.max_tokens = max_tokens;
|
|
833
874
|
job.out = run.out;
|
|
834
875
|
job.stats = run.stats;
|
|
@@ -1116,6 +1157,7 @@ typedef struct {
|
|
|
1116
1157
|
|
|
1117
1158
|
typedef struct {
|
|
1118
1159
|
VALUE ids_value;
|
|
1160
|
+
model_wrapper_t *owner;
|
|
1119
1161
|
const se_model_t *model;
|
|
1120
1162
|
uint32_t max_tokens;
|
|
1121
1163
|
uint32_t *ids;
|
|
@@ -1126,6 +1168,7 @@ typedef struct {
|
|
|
1126
1168
|
se_token_stats_t *stats_out;
|
|
1127
1169
|
se_token_stats_t stats;
|
|
1128
1170
|
int truncated;
|
|
1171
|
+
int active;
|
|
1129
1172
|
} ids_run_t;
|
|
1130
1173
|
|
|
1131
1174
|
typedef struct {
|
|
@@ -1197,7 +1240,11 @@ static VALUE embed_token_ids_body(VALUE arg) {
|
|
|
1197
1240
|
se_error_clear(&job.error);
|
|
1198
1241
|
|
|
1199
1242
|
if (run->n >= SE_IDS_GVL_UNLOCK_THRESHOLD) {
|
|
1243
|
+
run->owner->active_ops++;
|
|
1244
|
+
run->active = 1;
|
|
1200
1245
|
rb_thread_call_without_gvl(ids_execute, &job, ids_unblock_cancel, &job);
|
|
1246
|
+
run->owner->active_ops--;
|
|
1247
|
+
run->active = 0;
|
|
1201
1248
|
rb_thread_check_ints();
|
|
1202
1249
|
if (job.cancelled)
|
|
1203
1250
|
rb_raise(rb_eInterrupt, "operation cancelled");
|
|
@@ -1225,6 +1272,8 @@ static VALUE embed_token_ids_body(VALUE arg) {
|
|
|
1225
1272
|
|
|
1226
1273
|
static VALUE embed_token_ids_ensure(VALUE arg) {
|
|
1227
1274
|
ids_run_t *run = (ids_run_t *)(uintptr_t)arg;
|
|
1275
|
+
if (run->active)
|
|
1276
|
+
run->owner->active_ops--;
|
|
1228
1277
|
se_free(run->ids);
|
|
1229
1278
|
se_free(run->out);
|
|
1230
1279
|
run->ids = NULL;
|
|
@@ -1280,6 +1329,7 @@ static VALUE embed_token_ids_value(VALUE self, VALUE ids_value, VALUE max_tokens
|
|
|
1280
1329
|
ids_run_t run;
|
|
1281
1330
|
memset(&run, 0, sizeof(run));
|
|
1282
1331
|
run.ids_value = ids_value;
|
|
1332
|
+
run.owner = w;
|
|
1283
1333
|
run.model = &w->model;
|
|
1284
1334
|
run.max_tokens = max_tokens;
|
|
1285
1335
|
run.n = n;
|