Repository: ollama/ollama (language: go)

Issue:
System memory leak. Gemma3
### What is the issue?

When using Gemma3, system memory is fully consumed over time.
When using the qwen2.5 model, approximately 1.5Gb is consumed.

![Image](https://github.com/user-attachments/assets/0a333e7f-97c8-4142-b461-2336f2a8b1f1)

![Image](https://github.com/user-attachments/assets/601e291f-ae50-49be-a908-2d94e9b7f57f)

### Relevant log output

```shell
Mar 29 16:13:35 ai systemd[1]: Stopping ollama.service - Ollama Service...
Mar 29 16:13:35 ai systemd[1]: ollama.service: Deactivated successfully.
Mar 29 16:13:35 ai systemd[1]: Stopped ollama.service - Ollama Service.
Mar 29 16:13:35 ai systemd[1]: ollama.service: Consumed 1min 30.648s CPU time, 359.2M memory peak, 0B memory swap peak.
Mar 29 16:13:35 ai systemd[1]: Started ollama.service - Ollama Service.
Mar 29 16:13:35 ai ollama[143819]: 2025/03/29 16:13:35 routes.go:1230: INFO server config env="map[CUDA_VISIBLE_DEVICES: GPU_DEVICE_ORDINAL: HIP_VISIBLE_DEVICES: HSA_OVERRIDE_GFX_VERSION: HTTPS_PROXY: HTTP_PROXY: NO_PROXY: OLLAMA_CONTEXT_LENGTH:2048 OLLAMA_DEBUG:false OLLAMA_FLASH_ATTENTION:true OLLAMA_GPU_OVERHEAD:0 OLLAMA_HOST:http://127.0.0.1:11434 OLLAMA_INTEL_GPU:false OLLAMA_KEEP_ALIVE:2562047h47m16.854775807s OLLAMA_KV_CACHE_TYPE: OLLAMA_LLM_LIBRARY: OLLAMA_LOAD_TIMEOUT:5m0s OLLAMA_MAX_LOADED_MODELS:0 OLLAMA_MAX_QUEUE:512 OLLAMA_MODELS:/usr/share/ollama/.ollama/models OLLAMA_MULTIUSER_CACHE:false OLLAMA_NEW_ENGINE:false OLLAMA_NOHISTORY:false OLLAMA_NOPRUNE:false OLLAMA_NUM_PARALLEL:1 OLLAMA_ORIGINS:[http://localhost https://localhost http://localhost:* https://localhost:* http://127.0.0.1 https://127.0.0.1 http://127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://* vscode-webview://* vscode-file://*] OLLAMA_SCHED_SPREAD:false ROCR_VISIBLE_DEVICES: http_proxy: https_proxy: no_proxy:]"
Mar 29 16:13:35 ai ollama[143819]: time=2025-03-29T16:13:35.648+05:00 level=INFO source=images.go:432 msg="total blobs: 19"
Mar 29 16:13:35 ai ollama[143819]: time=2025-03-29T16:13:35.648+05:00 level=INFO source=images.go:439 msg="total unused blobs removed: 0"
Mar 29 16:13:35 ai ollama[143819]: time=2025-03-29T16:13:35.649+05:00 level=INFO source=routes.go:1297 msg="Listening on 127.0.0.1:11434 (version 0.6.3)"
Mar 29 16:13:35 ai ollama[143819]: time=2025-03-29T16:13:35.649+05:00 level=INFO source=gpu.go:217 msg="looking for compatible GPUs"
Mar 29 16:13:36 ai ollama[143819]: time=2025-03-29T16:13:36.035+05:00 level=INFO source=types.go:130 msg="inference compute" id=GPU-cf63f28b-b0a5-31c0-60a3-fde622d8ad0d library=cuda variant=v12 compute=8.6 driver=12.8 name="NVIDIA GeForce RTX 3090" total="23.5 GiB" available="23.3 GiB"
Mar 29 16:13:36 ai ollama[143819]: time=2025-03-29T16:13:36.892+05:00 level=INFO source=sched.go:715 msg="new model will fit in available VRAM in single GPU, loading" model=/usr/share/ollama/.ollama/models/blobs/sha256-fc57f67efa46d711c346e587cbef7d049e95f3df8db2eb2271153343ef0acc7b gpu=GPU-cf63f28b-b0a5-31c0-60a3-fde622d8ad0d parallel=1 available=24997330944 required="9.7 GiB"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.164+05:00 level=INFO source=server.go:105 msg="system memory" total="31.3 GiB" free="29.7 GiB" free_swap="8.0 GiB"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.439+05:00 level=INFO source=server.go:138 msg=offload library=cuda layers.requested=-1 layers.model=49 layers.offload=49 layers.split="" memory.available="[23.3 GiB]" memory.gpu_overhead="0 B" memory.required.full="9.7 GiB" memory.required.partial="9.7 GiB" memory.required.kv="992.0 MiB" memory.required.allocations="[9.7 GiB]" memory.weights.total="6.8 GiB" memory.weights.repeating="6.0 GiB" memory.weights.nonrepeating="787.5 MiB" memory.graph.full="519.5 MiB" memory.graph.partial="1.3 GiB" projector.weights="814.6 MiB" projector.graph="0 B"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.439+05:00 level=INFO source=server.go:185 msg="enabling flash attention"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.439+05:00 level=WARN source=server.go:193 msg="kv cache type not supported by model" type=""
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.489+05:00 level=WARN source=ggml.go:149 msg="key not found" key=tokenizer.ggml.pretokenizer default="(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.501+05:00 level=WARN source=ggml.go:149 msg="key not found" key=tokenizer.ggml.add_eot_token default=false
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.image_size default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.patch_size default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.num_channels default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.block_count default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.embedding_length default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.attention.head_count default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.image_size default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.patch_size default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.attention.layer_norm_epsilon default=0
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.505+05:00 level=WARN source=ggml.go:149 msg="key not found" key=tokenizer.ggml.pretokenizer default="(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.513+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.rope.local.freq_base default=10000
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.513+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.rope.global.freq_base default=1e+06
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.513+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.rope.freq_scale default=1
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.513+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.mm_tokens_per_image default=256
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.513+05:00 level=INFO source=server.go:405 msg="starting llama server" cmd="/usr/local/bin/ollama runner --ollama-engine --model /usr/share/ollama/.ollama/models/blobs/sha256-fc57f67efa46d711c346e587cbef7d049e95f3df8db2eb2271153343ef0acc7b --ctx-size 8192 --batch-size 512 --n-gpu-layers 49 --threads 6 --flash-attn --parallel 1 --port 35711"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.514+05:00 level=INFO source=sched.go:450 msg="loaded runners" count=1
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.514+05:00 level=INFO source=server.go:580 msg="waiting for llama runner to start responding"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.514+05:00 level=INFO source=server.go:614 msg="waiting for server to become available" status="llm server error"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.522+05:00 level=INFO source=runner.go:765 msg="starting ollama engine"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.522+05:00 level=INFO source=runner.go:828 msg="Server listening on 127.0.0.1:35711"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.575+05:00 level=WARN source=ggml.go:149 msg="key not found" key=general.description default=""
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.575+05:00 level=INFO source=ggml.go:69 msg="" architecture=gemma3 file_type=Q4_K_M name="Gemma 3 12b It" description="" num_tensors=626 num_key_values=45
Mar 29 16:13:37 ai ollama[143819]: ggml_cuda_init: GGML_CUDA_FORCE_MMQ:    no
Mar 29 16:13:37 ai ollama[143819]: ggml_cuda_init: GGML_CUDA_FORCE_CUBLAS: no
Mar 29 16:13:37 ai ollama[143819]: ggml_cuda_init: found 1 CUDA devices:
Mar 29 16:13:37 ai ollama[143819]:   Device 0: NVIDIA GeForce RTX 3090, compute capability 8.6, VMM: yes
Mar 29 16:13:37 ai ollama[143819]: load_backend: loaded CUDA backend from /usr/local/lib/ollama/cuda_v12/libggml-cuda.so
Mar 29 16:13:37 ai ollama[143819]: load_backend: loaded CPU backend from /usr/local/lib/ollama/libggml-cpu-haswell.so
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.638+05:00 level=INFO source=ggml.go:109 msg=system CPU.0.SSE3=1 CPU.0.SSSE3=1 CPU.0.AVX=1 CPU.0.AVX2=1 CPU.0.F16C=1 CPU.0.FMA=1 CPU.0.LLAMAFILE=1 CPU.1.LLAMAFILE=1 CUDA.0.ARCHS=500,600,610,700,750,800,860,870,890,900,1200 CUDA.0.USE_GRAPHS=1 CUDA.0.PEER_MAX_BATCH_SIZE=128 compiler=cgo(gcc)
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.765+05:00 level=INFO source=server.go:614 msg="waiting for server to become available" status="llm server loading model"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.816+05:00 level=INFO source=ggml.go:291 msg="model weights" buffer=CUDA0 size="6.8 GiB"
Mar 29 16:13:37 ai ollama[143819]: time=2025-03-29T16:13:37.816+05:00 level=INFO source=ggml.go:291 msg="model weights" buffer=CPU size="787.5 MiB"
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.824+05:00 level=INFO source=ggml.go:383 msg="compute graph" backend=CUDA0 buffer_type=CUDA0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.824+05:00 level=INFO source=ggml.go:383 msg="compute graph" backend=CPU buffer_type=CUDA_Host
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.824+05:00 level=WARN source=ggml.go:149 msg="key not found" key=tokenizer.ggml.pretokenizer default="(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.828+05:00 level=WARN source=ggml.go:149 msg="key not found" key=tokenizer.ggml.add_eot_token default=false
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.image_size default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.patch_size default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.num_channels default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.block_count default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.embedding_length default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.attention.head_count default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.image_size default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.patch_size default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.vision.attention.layer_norm_epsilon default=0
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.831+05:00 level=WARN source=ggml.go:149 msg="key not found" key=tokenizer.ggml.pretokenizer default="(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}{1,3}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.840+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.rope.local.freq_base default=10000
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.840+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.rope.global.freq_base default=1e+06
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.840+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.rope.freq_scale default=1
Mar 29 16:13:38 ai ollama[143819]: time=2025-03-29T16:13:38.840+05:00 level=WARN source=ggml.go:149 msg="key not found" key=gemma3.mm_tokens_per_image default=256
Mar 29 16:13:39 ai ollama[143819]: time=2025-03-29T16:13:39.020+05:00 level=INFO source=server.go:619 msg="llama runner started in 1.51 seconds"
Mar 29 16:13:39 ai ollama[143819]: [GIN] 2025/03/29 - 16:13:39 | 200 |  2.669877938s |       127.0.0.1 | POST     "/api/generate"
```

### OS

Linux

### GPU

Nvidia

### CPU

Intel

### Ollama version

0.6.3


Discussion / hints:

Fix patch:
diff --git a/ml/backend/ggml/ggml.go b/ml/backend/ggml/ggml.go
index 24bdd903ded..d187a400a39 100644
--- a/ml/backend/ggml/ggml.go
+++ b/ml/backend/ggml/ggml.go
@@ -382,12 +382,6 @@ func New(ctx context.Context, r *os.File, params ml.BackendParams) (ml.Backend,
 	for _, d := range append(gpus, append(accels, cpus...)...) {
 		b := C.ggml_backend_dev_init(d, nil)
 		bt := C.ggml_backend_get_default_buffer_type(b)
-		if d := C.ggml_backend_get_device(b); C.ggml_backend_dev_type(d) == C.GGML_BACKEND_DEVICE_TYPE_CPU && len(gpus) > 0 {
-			// use the first gpu host buffer type for gpu if possible
-			if hbt := C.ggml_backend_dev_host_buffer_type(gpus[0]); hbt != nil {
-				bt = hbt
-			}
-		}
 
 		deviceBufferTypes[d] = bt
 
@@ -451,6 +445,8 @@ func (b *Backend) NewContextSize(n int) ml.Context {
 		panic(fmt.Errorf("requested number of graph nodes (%v) for new context exceeds maximum (%v)", n, b.maxGraphNodes))
 	}
 
+	var allocatedBuffers []*C.struct_ggml_backend_buffer
+
 	return &Context{
 		b:             b,
 		maxGraphNodes: n,
@@ -458,6 +454,7 @@ func (b *Backend) NewContextSize(n int) ml.Context {
 			mem_size: C.size_t(n)*C.ggml_tensor_overhead() + C.ggml_graph_overhead_custom(C.size_t(n), false),
 			no_alloc: true,
 		}),
+		allocatedBuffers: &allocatedBuffers,
 	}
 }
 
@@ -478,34 +475,40 @@ type Context struct {
 	// buft is the buffer type used for new tensors
 	buft *C.struct_ggml_backend_buffer_type
 
+	// allocatedBuffers are buffers for tensors that we have allocated in this context
+	// so that we can free them when we close the context
+	allocatedBuffers *[]*C.struct_ggml_backend_buffer
+
 	// maxGraphNodes is the maximum allowed number of graph nodes in this context
 	maxGraphNodes int
 }
 
-func (c Context) Input() ml.Context {
+func (c *Context) Input() ml.Context {
 	if c.b.input != nil {
 		return &Context{
-			b:             c.b,
-			ctx:           c.ctx,
-			buft:          c.b.input,
-			maxGraphNodes: c.maxGraphNodes,
+			b:                c.b,
+			ctx:              c.ctx,
+			buft:             c.b.input,
+			allocatedBuffers: c.allocatedBuffers,
+			maxGraphNodes:    c.maxGraphNodes,
 		}
 	}
 
-	return &c
+	return c
 }
 
-func (c Context) Layer(i int) ml.Context {
+func (c *Context) Layer(i int) ml.Context {
 	if buft, ok := c.b.layers[i]; ok {
 		return &Context{
-			b:             c.b,
-			ctx:           c.ctx,
-			buft:          buft,
-			maxGraphNodes: c.maxGraphNodes,
+			b:                c.b,
+			ctx:              c.ctx,
+			buft:             buft,
+			allocatedBuffers: c.allocatedBuffers,
+			maxGraphNodes:    c.maxGraphNodes,
 		}
 	}
 
-	return &c
+	return c
 }
 
 func (c *Context) Forward(tensors ...ml.Tensor) ml.Context {
@@ -520,7 +523,7 @@ func (c *Context) Forward(tensors ...ml.Tensor) ml.Context {
 	return c
 }
 
-func (c Context) Compute(tensors ...ml.Tensor) {
+func (c *Context) Compute(tensors ...ml.Tensor) {
 	C.ggml_backend_sched_graph_compute_async(c.b.sched, c.graph)
 	C.ggml_backend_sched_reset(c.b.sched)
 
@@ -539,7 +542,7 @@ func (c Context) Compute(tensors ...ml.Tensor) {
 	}
 }
 
-func (c Context) Reserve() error {
+func (c *Context) Reserve() error {
 	if !C.ggml_backend_sched_reserve(c.b.sched, c.graph) {
 		C.ggml_backend_sched_reset(c.b.sched)
 		return errors.New("failed to reserve graph")
@@ -557,7 +560,7 @@ func (c Context) Reserve() error {
 	return nil
 }
 
-func (c Context) MaxGraphNodes() int {
+func (c *Context) MaxGraphNodes() int {
 	return c.maxGraphNodes
 }
 
@@ -574,7 +577,7 @@ func pad(length, pad C.size_t) C.size_t {
 	return ((length + pad - 1) / pad) * pad
 }
 
-func (c Context) newTensor(dtype ml.DType, shape []int) (ml.Tensor, error) {
+func (c *Context) newTensor(dtype ml.DType, shape []int) (ml.Tensor, error) {
 	if c.buft == nil {
 		panic("set Input or Layer before creating tensors")
 	}
@@ -614,12 +617,13 @@ func (c Context) newTensor(dtype ml.DType, shape []int) (ml.Tensor, error) {
 	if b == nil {
 		return nil, fmt.Errorf("unable to allocate %v from device %v for new tensor", format.HumanBytes2(uint64(size)), C.GoString(C.ggml_backend_buft_name(c.buft)))
 	}
+	*c.allocatedBuffers = append(*c.allocatedBuffers, b)
 
 	C.ggml_backend_tensor_alloc(b, t, C.ggml_backend_buffer_get_base(b))
 	return &Tensor{b: c.b, t: t}, nil
 }
 
-func (c Context) Empty(dtype ml.DType, shape ...int) ml.Tensor {
+func (c *Context) Empty(dtype ml.DType, shape ...int) ml.Tensor {
 	t, err := c.newTensor(dtype, shape)
 	if err != nil {
 		panic(err)
@@ -628,7 +632,7 @@ func (c Context) Empty(dtype ml.DType, shape ...int) ml.Tensor {
 	return t
 }
 
-func (c Context) Zeros(dtype ml.DType, shape ...int) ml.Tensor {
+func (c *Context) Zeros(dtype ml.DType, shape ...int) ml.Tensor {
 	t, err := c.newTensor(dtype, shape)
 	if err != nil {
 		panic(err)
@@ -656,7 +660,7 @@ func checkShape[S ~[]E, E any](s S, shape ...int) error {
 	return nil
 }
 
-func (c Context) FromFloatSlice(s []float32, shape ...int) (ml.Tensor, error) {
+func (c *Context) FromFloatSlice(s []float32, shape ...int) (ml.Tensor, error) {
 	if err := checkShape(s, shape...); err != nil {
 		return nil, err
 	}
@@ -673,7 +677,7 @@ func (c Context) FromFloatSlice(s []float32, shape ...int) (ml.Tensor, error) {
 	return t, nil
 }
 
-func (c Context) FromIntSlice(s []int32, shape ...int) (ml.Tensor, error) {
+func (c *Context) FromIntSlice(s []int32, shape ...int) (ml.Tensor, error) {
 	if err := checkShape(s, shape...); err != nil {
 		return nil, err
 	}
@@ -692,6 +696,11 @@ func (c Context) FromIntSlice(s []int32, shape ...int) (ml.Tensor, error) {
 
 func (c *Context) Close() {
 	if c != nil {
+		for _, b := range *c.allocatedBuffers {
+			C.ggml_backend_buffer_free(b)
+		}
+		*c.allocatedBuffers = nil
+
 		C.ggml_free(c.ctx)
 	}
 }


Test patch: