Add ggml_tensor_required_memory function to calculate how much memory creating a tensor will require.
Also add ggml_used_scratch_mem function so applications can determine how much scratch memory was used.
This commit is contained in:
parent
1b0fd45465
commit
89951748db
2 changed files with 68 additions and 20 deletions
74
ggml.c
74
ggml.c
|
@ -4615,6 +4615,10 @@ size_t ggml_used_mem(const struct ggml_context * ctx) {
|
||||||
return ctx->objects_end == NULL ? 0 : ctx->objects_end->offs + ctx->objects_end->size;
|
return ctx->objects_end == NULL ? 0 : ctx->objects_end->offs + ctx->objects_end->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ggml_used_scratch_mem(const struct ggml_context * ctx) {
|
||||||
|
return ctx->scratch.data == NULL ? 0 : ctx->scratch.offs;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ggml_set_scratch(struct ggml_context * ctx, struct ggml_scratch scratch) {
|
size_t ggml_set_scratch(struct ggml_context * ctx, struct ggml_scratch scratch) {
|
||||||
const size_t result = ctx->scratch.data ? ctx->scratch.offs : 0;
|
const size_t result = ctx->scratch.data ? ctx->scratch.offs : 0;
|
||||||
|
|
||||||
|
@ -4623,6 +4627,41 @@ size_t ggml_set_scratch(struct ggml_context * ctx, struct ggml_scratch scratch)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ggml_tensor_required_memory(
|
||||||
|
struct ggml_context * ctx,
|
||||||
|
enum ggml_type type,
|
||||||
|
int n_dims,
|
||||||
|
const int64_t* ne,
|
||||||
|
void* data,
|
||||||
|
size_t * required_ctx,
|
||||||
|
size_t * required_scratch) {
|
||||||
|
struct ggml_object * obj_cur = ctx->objects_end;
|
||||||
|
const size_t cur_offs = obj_cur == NULL ? 0 : obj_cur->offs;
|
||||||
|
const size_t cur_size = obj_cur == NULL ? 0 : obj_cur->size;
|
||||||
|
const size_t cur_end = cur_offs + cur_size;
|
||||||
|
|
||||||
|
size_t size_needed = 0;
|
||||||
|
|
||||||
|
if (data == NULL && !ctx->no_alloc) {
|
||||||
|
size_needed += GGML_TYPE_SIZE[type]*(ne[0]/GGML_BLCK_SIZE[type]);
|
||||||
|
for (int i = 1; i < n_dims; i++) {
|
||||||
|
size_needed *= ne[i];
|
||||||
|
}
|
||||||
|
// align to GGML_MEM_ALIGN
|
||||||
|
size_needed = ((size_needed + GGML_MEM_ALIGN - 1)/GGML_MEM_ALIGN)*GGML_MEM_ALIGN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->scratch.data == NULL || data != NULL) {
|
||||||
|
*required_ctx += size_needed + sizeof(struct ggml_tensor) + GGML_OBJECT_SIZE;
|
||||||
|
return cur_end + *required_ctx <= ctx->mem_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
*required_ctx += sizeof(struct ggml_tensor) + GGML_OBJECT_SIZE;
|
||||||
|
*required_scratch += size_needed;
|
||||||
|
return ctx->scratch.offs + *required_scratch <= ctx->scratch.size &&
|
||||||
|
cur_end + *required_ctx <= ctx->mem_size;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct ggml_tensor * ggml_new_tensor_impl(
|
struct ggml_tensor * ggml_new_tensor_impl(
|
||||||
|
@ -4638,8 +4677,23 @@ struct ggml_tensor * ggml_new_tensor_impl(
|
||||||
const size_t cur_size = obj_cur == NULL ? 0 : obj_cur->size;
|
const size_t cur_size = obj_cur == NULL ? 0 : obj_cur->size;
|
||||||
const size_t cur_end = cur_offs + cur_size;
|
const size_t cur_end = cur_offs + cur_size;
|
||||||
|
|
||||||
|
size_t ctx_needed = 0;
|
||||||
|
size_t scratch_needed = 0;
|
||||||
|
|
||||||
size_t size_needed = 0;
|
size_t size_needed = 0;
|
||||||
|
|
||||||
|
if (!ggml_tensor_required_memory(ctx, type, n_dims, ne, data, &ctx_needed, &scratch_needed)) {
|
||||||
|
if (scratch_needed > 0 && ctx->scratch.size) {
|
||||||
|
GGML_PRINT("%s: not enough space in the scratch memory (needed %zu, available %zu)\n",
|
||||||
|
__func__, ctx->scratch.offs + scratch_needed, ctx->scratch.size);
|
||||||
|
} else {
|
||||||
|
GGML_PRINT("%s: not enough space in the context's memory pool (needed %zu, available %zu)\n",
|
||||||
|
__func__, cur_end + ctx_needed, ctx->mem_size);
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (data == NULL && !ctx->no_alloc) {
|
if (data == NULL && !ctx->no_alloc) {
|
||||||
size_needed += GGML_TYPE_SIZE[type]*(ne[0]/GGML_BLCK_SIZE[type]);
|
size_needed += GGML_TYPE_SIZE[type]*(ne[0]/GGML_BLCK_SIZE[type]);
|
||||||
for (int i = 1; i < n_dims; i++) {
|
for (int i = 1; i < n_dims; i++) {
|
||||||
|
@ -4655,32 +4709,12 @@ struct ggml_tensor * ggml_new_tensor_impl(
|
||||||
if (ctx->scratch.data == NULL || data != NULL) {
|
if (ctx->scratch.data == NULL || data != NULL) {
|
||||||
size_needed += sizeof(struct ggml_tensor);
|
size_needed += sizeof(struct ggml_tensor);
|
||||||
|
|
||||||
if (cur_end + size_needed + GGML_OBJECT_SIZE > ctx->mem_size) {
|
|
||||||
GGML_PRINT("%s: not enough space in the context's memory pool (needed %zu, available %zu)\n",
|
|
||||||
__func__, cur_end + size_needed + GGML_OBJECT_SIZE, ctx->mem_size);
|
|
||||||
assert(false);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*obj_new = (struct ggml_object) {
|
*obj_new = (struct ggml_object) {
|
||||||
.offs = cur_end + GGML_OBJECT_SIZE,
|
.offs = cur_end + GGML_OBJECT_SIZE,
|
||||||
.size = size_needed,
|
.size = size_needed,
|
||||||
.next = NULL,
|
.next = NULL,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (ctx->scratch.offs + size_needed > ctx->scratch.size) {
|
|
||||||
GGML_PRINT("%s: not enough space in the scratch memory\n", __func__);
|
|
||||||
assert(false);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur_end + sizeof(struct ggml_tensor) + GGML_OBJECT_SIZE > ctx->mem_size) {
|
|
||||||
GGML_PRINT("%s: not enough space in the context's memory pool (needed %zu, available %zu)\n",
|
|
||||||
__func__, cur_end + sizeof(struct ggml_tensor) + GGML_OBJECT_SIZE, ctx->mem_size);
|
|
||||||
assert(false);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = (char * const) ctx->scratch.data + ctx->scratch.offs;
|
data = (char * const) ctx->scratch.data + ctx->scratch.offs;
|
||||||
|
|
||||||
*obj_new = (struct ggml_object) {
|
*obj_new = (struct ggml_object) {
|
||||||
|
|
14
ggml.h
14
ggml.h
|
@ -422,6 +422,20 @@ extern "C" {
|
||||||
GGML_API void ggml_free(struct ggml_context * ctx);
|
GGML_API void ggml_free(struct ggml_context * ctx);
|
||||||
|
|
||||||
GGML_API size_t ggml_used_mem(const struct ggml_context * ctx);
|
GGML_API size_t ggml_used_mem(const struct ggml_context * ctx);
|
||||||
|
GGML_API size_t ggml_used_scratch_mem(const struct ggml_context * ctx);
|
||||||
|
|
||||||
|
// Calculate the memory required to construct a tensor with the specified type,
|
||||||
|
// dimensions and shape. The last two arguments will be incremented by the
|
||||||
|
// required sizes so it's necessary to initialize them to 0 before calling this
|
||||||
|
// function for the first time.
|
||||||
|
GGML_API bool ggml_tensor_required_memory(
|
||||||
|
struct ggml_context * ctx,
|
||||||
|
enum ggml_type type,
|
||||||
|
int n_dims,
|
||||||
|
const int64_t* ne,
|
||||||
|
void* data,
|
||||||
|
size_t * required_ctx,
|
||||||
|
size_t * required_scratch);
|
||||||
|
|
||||||
GGML_API size_t ggml_set_scratch(struct ggml_context * ctx, struct ggml_scratch scratch);
|
GGML_API size_t ggml_set_scratch(struct ggml_context * ctx, struct ggml_scratch scratch);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue