Lugh
view release on metacpan or search on metacpan
lib/Lugh.xs view on Meta::CPAN
CONTEXT_LOCK();
lctx = context_registry[id];
if (lctx && !lctx->active) lctx = NULL;
CONTEXT_UNLOCK();
return lctx;
}
/* Allocate a new tensor ID */
static int alloc_tensor_id(void) {
int id = -1;
TENSOR_LOCK();
for (int i = 0; i < MAX_TENSORS; i++) {
int check_id = (next_tensor_id + i) % MAX_TENSORS;
if (check_id == 0) check_id = 1;
if (tensor_registry[check_id] == NULL) {
id = check_id;
next_tensor_id = (id + 1) % MAX_TENSORS;
if (next_tensor_id == 0) next_tensor_id = 1;
break;
}
}
TENSOR_UNLOCK();
return id;
}
/* Get tensor by ID */
static LughTensor* get_tensor_by_id(int id) {
LughTensor *lt = NULL;
if (id <= 0 || id >= MAX_TENSORS) return NULL;
TENSOR_LOCK();
lt = tensor_registry[id];
if (lt && !lt->active) lt = NULL;
TENSOR_UNLOCK();
return lt;
}
/* Create a new LughTensor and register it */
static LughTensor* create_lugh_tensor(pTHX_ struct ggml_tensor *tensor, int context_id, bool requires_grad) {
LughTensor *lt;
int id;
if (!tensor) return NULL;
id = alloc_tensor_id();
if (id < 0) {
croak("Tensor registry full (max %d tensors)", MAX_TENSORS);
return NULL;
}
Newxz(lt, 1, LughTensor);
if (!lt) {
croak("Failed to allocate LughTensor");
return NULL;
}
lt->tensor = tensor;
lt->grad = NULL;
lt->context_id = context_id;
lt->id = id;
lt->active = 1;
lt->requires_grad = requires_grad;
lt->backward_op = LUGH_BACKWARD_NONE;
lt->n_inputs = 0;
lt->is_leaf = true; /* Default: leaf tensor */
lt->grad_accumulated = false;
/* Initialize input_ids to -1 (invalid) */
for (int i = 0; i < 4; i++) {
lt->input_ids[i] = -1;
}
TENSOR_LOCK();
tensor_registry[id] = lt;
TENSOR_UNLOCK();
return lt;
}
/* Free a LughTensor and remove from registry */
static void free_lugh_tensor(LughTensor *lt) {
if (!lt) return;
TENSOR_LOCK();
if (lt->id > 0 && lt->id < MAX_TENSORS) {
tensor_registry[lt->id] = NULL;
}
lt->active = 0;
TENSOR_UNLOCK();
/* Note: tensor->data is owned by the context, not freed here */
/* Note: grad tensor is also owned by the context */
Safefree(lt);
}
/* Allocate gradient tensor for a LughTensor (same shape as original) */
static int alloc_grad(pTHX_ LughTensor *lt, LughContext *lctx) {
if (!lt || !lctx || !lt->tensor) return 0;
if (lt->grad) return 1; /* Already allocated */
/* Create gradient tensor with same shape as original */
struct ggml_tensor *grad = ggml_dup_tensor(lctx->ctx, lt->tensor);
if (!grad) return 0;
/* Ensure memory is allocated */
if (!grad->data) {
/* If ggml didn't allocate, we have a problem */
return 0;
}
/* Zero-initialize the gradient using explicit memset */
size_t nbytes = ggml_nbytes(grad);
memset(grad->data, 0, nbytes);
/* Force a memory barrier */
__sync_synchronize();
lt->grad = grad;
return 1;
}
/* Zero out all accumulated gradients */
( run in 1.345 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )