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 )