Skip to contentSkip to conversation

GPU memory aligned

PATCH Superseded [email protected] 3 participants 12 messages Jan 3, 2022 – Jan 21, 2022 DRM drivers

lore
Share & tools
lore
#0 lore raw

cover GPU memory aligned

From: Elena Agostini <[email protected]>

Applications may need to allocate GPU memory buffers with memory address aligned to some value (e.g. page size).

Similarly to the rte_malloc function, aligned size can be provided as input to rte_gpu_mem_alloc.

This set of patches implements this functionality in the gpudev library and the GPU CUDA driver.

Elena Agostini (3):
gpudev: mem alloc aligned memory app/test-gpudev: test aligned memory allocation gpu/cuda: mem alloc aligned memory

 app/test-gpudev/main.c     | 13 ++++++++++---
 drivers/gpu/cuda/cuda.c    | 21 ++++++++++++++++-----
 lib/gpudev/gpudev.c        | 10 ++++++++--
 lib/gpudev/gpudev_driver.h |  2 +-
 lib/gpudev/rte_gpudev.h    | 10 +++++++---
 5 files changed, 42 insertions(+), 14 deletions(-)
Signature · 1 line
2.17.1
#1 lore raw

PATCH 1/3 gpudev: mem alloc aligned memory

From: Elena Agostini <[email protected]>

Similarly to rte_malloc, rte_gpu_mem_alloc accept as input the memory alignment size.

GPU driver should return GPU memory address aligned with the input value.

---
 lib/gpudev/gpudev.c        | 10 ++++++++--
 lib/gpudev/gpudev_driver.h |  2 +-
 lib/gpudev/rte_gpudev.h    | 10 +++++++---
 3 files changed, 16 insertions(+), 6 deletions(-)
lib/gpudev/gpudev.c +8 -2
index 9ae36dbae9..dc8c3baefa 100644
@@ -527,7 +527,7 @@ rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info)
 }
 
 void *
-rte_gpu_mem_alloc(int16_t dev_id, size_t size)
+rte_gpu_mem_alloc(int16_t dev_id, size_t size, unsigned int align)
 {
 	struct rte_gpu *dev;
 	void *ptr;
@@ -549,7 +549,13 @@ rte_gpu_mem_alloc(int16_t dev_id, size_t size)
 	if (size == 0) /* dry-run */
 		return NULL;
 
-	ret = dev->ops.mem_alloc(dev, size, &ptr);
+	if (align && !rte_is_power_of_2(align)) {
+		GPU_LOG(ERR, "requested alignment is not a power of two %u", align);
+		rte_errno = EINVAL;
+		return NULL;
+	}
+
+	ret = dev->ops.mem_alloc(dev, size, &ptr, align);
 
 	switch (ret) {
 	case 0:
lib/gpudev/gpudev_driver.h +1 -1
index cb7b101f2f..d06f465194 100644
@@ -27,7 +27,7 @@ enum rte_gpu_state {
 struct rte_gpu;
 typedef int (rte_gpu_close_t)(struct rte_gpu *dev);
 typedef int (rte_gpu_info_get_t)(struct rte_gpu *dev, struct rte_gpu_info *info);
-typedef int (rte_gpu_mem_alloc_t)(struct rte_gpu *dev, size_t size, void **ptr);
+typedef int (rte_gpu_mem_alloc_t)(struct rte_gpu *dev, size_t size, void **ptr, unsigned int align);
 typedef int (rte_gpu_mem_free_t)(struct rte_gpu *dev, void *ptr);
 typedef int (rte_gpu_mem_register_t)(struct rte_gpu *dev, size_t size, void *ptr);
 typedef int (rte_gpu_mem_unregister_t)(struct rte_gpu *dev, void *ptr);
lib/gpudev/rte_gpudev.h +7 -3
index fa3f3aad4f..9e2e2c5dce 100644
@@ -364,18 +364,22 @@ int rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info);
  * @param size
  *   Number of bytes to allocate.
  *   Requesting 0 will do nothing.
- *
+ * @param align
+ *   If 0, the return is a pointer that is suitably aligned for any kind of
+ *   variable (in the same manner as malloc()).
+ *   Otherwise, the return is a pointer that is a multiple of *align*. In
+ *   this case, it must obviously be a power of two.
  * @return
  *   A pointer to the allocated memory, otherwise NULL and rte_errno is set:
  *   - ENODEV if invalid dev_id
- *   - EINVAL if reserved flags
+ *   - EINVAL if align is not a power of two
  *   - ENOTSUP if operation not supported by the driver
  *   - E2BIG if size is higher than limit
  *   - ENOMEM if out of space
  *   - EPERM if driver error
  */
 __rte_experimental
-void *rte_gpu_mem_alloc(int16_t dev_id, size_t size)
+void *rte_gpu_mem_alloc(int16_t dev_id, size_t size, unsigned int align)
 __rte_alloc_size(2);
 
 /**
Signature · 1 line
2.17.1
#2 lore raw

PATCH 2/3 app/test-gpudev: test aligned memory allocation

In reply to [email protected]

From: Elena Agostini <[email protected]>

Update gpudev app to test GPU memory aligned allocation.

---
 app/test-gpudev/main.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
app/test-gpudev/main.c +10 -3
index 5c1aa3d52f..f36f46cbca 100644
@@ -69,11 +69,12 @@ alloc_gpu_memory(uint16_t gpu_id)
 	void *ptr_2 = NULL;
 	size_t buf_bytes = 1024;
 	int ret;
+	unsigned align = 4096;
 
 	printf("\n=======> TEST: Allocate GPU memory\n\n");
 
-	/* Alloc memory on GPU 0 */
-	ptr_1 = rte_gpu_mem_alloc(gpu_id, buf_bytes);
+	/* Alloc memory on GPU 0 without any specific alignment */
+	ptr_1 = rte_gpu_mem_alloc(gpu_id, buf_bytes, 0);
 	if (ptr_1 == NULL) {
 		fprintf(stderr, "rte_gpu_mem_alloc GPU memory returned error\n");
 		goto error;
@@ -81,7 +82,8 @@ alloc_gpu_memory(uint16_t gpu_id)
 	printf("GPU memory allocated at 0x%p size is %zd bytes\n",
 			ptr_1, buf_bytes);
 
-	ptr_2 = rte_gpu_mem_alloc(gpu_id, buf_bytes);
+	/* Alloc memory on GPU 0 with 4kB alignment */
+	ptr_2 = rte_gpu_mem_alloc(gpu_id, buf_bytes, align);
 	if (ptr_2 == NULL) {
 		fprintf(stderr, "rte_gpu_mem_alloc GPU memory returned error\n");
 		goto error;
@@ -89,6 +91,11 @@ alloc_gpu_memory(uint16_t gpu_id)
 	printf("GPU memory allocated at 0x%p size is %zd bytes\n",
 			ptr_2, buf_bytes);
 
+	if (((uintptr_t)ptr_2) % align) {
+		fprintf(stderr, "Memory address 0x%p is not aligned to %u\n", ptr_2, align);
+		goto error;
+	}
+
 	ret = rte_gpu_mem_free(gpu_id, (uint8_t *)(ptr_1)+0x700);
 	if (ret < 0) {
 		printf("GPU memory 0x%p NOT freed: GPU driver didn't find this memory address internally.\n",
Signature · 1 line
2.17.1
#3 lore raw

PATCH 3/3 gpu/cuda: mem alloc aligned memory

In reply to [email protected]

From: Elena Agostini <[email protected]>

Implement aligned GPU memory allocation in GPU CUDA driver.

---
 drivers/gpu/cuda/cuda.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/gpu/cuda/cuda.c +16 -5
index 882df08e56..4ad3f5fc90 100644
@@ -139,8 +139,10 @@ typedef uintptr_t cuda_ptr_key;
 /* Single entry of the memory list */
 struct mem_entry {
 	CUdeviceptr ptr_d;
+	CUdeviceptr ptr_orig_d;
 	void *ptr_h;
 	size_t size;
+	size_t size_orig;
 	struct rte_gpu *dev;
 	CUcontext ctx;
 	cuda_ptr_key pkey;
@@ -569,7 +571,7 @@ cuda_dev_info_get(struct rte_gpu *dev, struct rte_gpu_info *info)
  */
 
 static int
-cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
+cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr, unsigned int align)
 {
 	CUresult res;
 	const char *err_string;
@@ -610,8 +612,10 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 
 	/* Allocate memory */
 	mem_alloc_list_tail->size = size;
-	res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_d),
-			mem_alloc_list_tail->size);
+	mem_alloc_list_tail->size_orig = size + align;
+
+	res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d),
+			mem_alloc_list_tail->size_orig);
 	if (res != 0) {
 		pfn_cuGetErrorString(res, &(err_string));
 		rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
@@ -620,6 +624,13 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 		return -rte_errno;
 	}
 
+
+	/* Align memory address */
+	mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d;
+	if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align)
+		mem_alloc_list_tail->ptr_d += (align -
+				(((uintptr_t)mem_alloc_list_tail->ptr_d) % align));
+
 	/* GPUDirect RDMA attribute required */
 	res = pfn_cuPointerSetAttribute(&flag,
 			CU_POINTER_ATTRIBUTE_SYNC_MEMOPS,
@@ -634,7 +645,6 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 
 	mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_d);
 	mem_alloc_list_tail->ptr_h = NULL;
-	mem_alloc_list_tail->size = size;
 	mem_alloc_list_tail->dev = dev;
 	mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
 	mem_alloc_list_tail->mtype = GPU_MEM;
@@ -761,6 +771,7 @@ cuda_mem_register(struct rte_gpu *dev, size_t size, void *ptr)
 	mem_alloc_list_tail->dev = dev;
 	mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
 	mem_alloc_list_tail->mtype = CPU_REGISTERED;
+	mem_alloc_list_tail->ptr_orig_d = mem_alloc_list_tail->ptr_d;
 
 	/* Restore original ctx as current ctx */
 	res = pfn_cuCtxSetCurrent(current_ctx);
@@ -796,7 +807,7 @@ cuda_mem_free(struct rte_gpu *dev, void *ptr)
 	}
 
 	if (mem_item->mtype == GPU_MEM) {
-		res = pfn_cuMemFree(mem_item->ptr_d);
+		res = pfn_cuMemFree(mem_item->ptr_orig_d);
 		if (res != 0) {
 			pfn_cuGetErrorString(res, &(err_string));
 			rte_cuda_log(ERR, "cuMemFree current failed with %s",
Signature · 1 line
2.17.1
#4 lore raw

Re: [PATCH v1 3/3] gpu/cuda: mem alloc aligned memory

Quoted 20 lines · On Tue, 4 Jan 2022 01:47:21 +0000 <[email protected]> wrote:

static int

drivers/gpu/cuda/cuda.c +5 -3
-cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
+cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr, unsigned int align)
 {
 	CUresult res;
 	const char *err_string;
@@ -610,8 +612,10 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 
 	/* Allocate memory */
 	mem_alloc_list_tail->size = size;
-	res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_d),
-			mem_alloc_list_tail->size);
+	mem_alloc_list_tail->size_orig = size + align;
+
+	res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d),
+			mem_alloc_list_tail->size_orig);
 	if (res != 0) {
 		pfn_cuGetErrorString(res, &(err_string));
 		rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",

drivers/gpu/cuda/cuda.c cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr) · line 632

Quoted 9 lines
drivers/gpu/cuda/cuda.c +6 -0
@@ -620,6 +624,13 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 		return -rte_errno;
 	}
 
+
+	/* Align memory address */
+	mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d;
+	if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align)
+		mem_alloc_list_tail->ptr_d += (align -
+				(((uintptr_t)mem_alloc_list_tail->ptr_d) % align));

Posix memalign takes size_t for both size and alignment.

Better to put the input parameters first, and then the resulting output parameter last for consistency; follows the Rusty API design manifesto.

Alignment only makes sense if power of two. The code should check that and optimize for that.

#5 lore raw

Re: [PATCH v1 3/3] gpu/cuda: mem alloc aligned memory

Quoted 34 lines

From: Stephen Hemminger <[email protected]>
Date: Monday, 3 January 2022 at 19:05
To: Elena Agostini <[email protected]>
Cc: [email protected] <[email protected]>
Subject: Re: [PATCH v1 3/3] gpu/cuda: mem alloc aligned memory External email: Use caution opening links or attachments>

On Tue, 4 Jan 2022 01:47:21 +0000
<[email protected]> wrote:>

Quoted 23 lines

static int

drivers/gpu/cuda/cuda.c +5 -3
-cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
+cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr, unsigned int align)
 {
      CUresult res;
      const char *err_string;
@@ -610,8 +612,10 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 
      /* Allocate memory */
      mem_alloc_list_tail->size = size;
-     res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_d),
-                     mem_alloc_list_tail->size);
+     mem_alloc_list_tail->size_orig = size + align;
+
+     res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d),
+                     mem_alloc_list_tail->size_orig);
      if (res != 0) {
              pfn_cuGetErrorString(res, &(err_string));
              rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
@@ -620,6 +624,13 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
              return -rte_errno;
      }
 
Quoted 9 lines

drivers/gpu/cuda/cuda.c cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)

Quoted 6 lines
drivers/gpu/cuda/cuda.c +6 -0
+
+     /* Align memory address */
+     mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d;
+     if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align)
+             mem_alloc_list_tail->ptr_d += (align -
+                             (((uintptr_t)mem_alloc_list_tail->ptr_d) % align));>

Posix memalign takes size_t for both size and alignment.

I've created this patch based on the rte_malloc function definition for consistency.

void * rte_malloc(const char *type, size_t size, unsigned align)

Quoted 2 lines

Better to put the input parameters first, and then the resulting output parameter last for consistency; follows the Rusty API design manifesto.

Got it, will do.

Quoted 3 lines

Alignment only makes sense if power of two. The code should check that and optimize for that.

The alignment value is checked in the gpudev library before passing it to the driver.

Adding this kind of checks in the driver has been rejected in the past because it was considered dead code (the library was already checking input parameters).

Let me know what are the preferred options.

#6 lore raw

Re: [PATCH v1 3/3] gpu/cuda: mem alloc aligned memory

Quoted 11 lines · On Mon, 3 Jan 2022 18:15:11 +0000 Elena Agostini <[email protected]> wrote:
Quoted 3 lines

Alignment only makes sense if power of two. The code should check that and optimize for that.

The alignment value is checked in the gpudev library before passing it to the driver.

Adding this kind of checks in the driver has been rejected in the past because it was considered dead code (the library was already checking input parameters).

Let me know what are the preferred options.

Driver could use the mask instead of slow divide operation.

#7 lore raw

Re: [PATCH v1 3/3] gpu/cuda: mem alloc aligned memory

Quoted 10 lines
Quoted 7 lines · On Mon, 3 Jan 2022 18:15:11 +0000 Elena Agostini <[email protected]> wrote:
Quoted 3 lines

Alignment only makes sense if power of two. The code should check that and optimize for that.

The alignment value is checked in the gpudev library before passing it to the driver.

Quoted 6 lines
Quoted 4 lines

Adding this kind of checks in the driver has been rejected in the past because it was considered dead code (the library was already checking input parameters).

Let me know what are the preferred options.

Driver could use the mask instead of slow divide operation.

I'd not be concerned about performance here. Memory allocation is expensive, typically you want to do it at initialization time.

What do you suggest for my other comments?

#8 lore raw

PATCH v2 1/3 gpudev: mem alloc aligned memory

In reply to [email protected]

From: Elena Agostini <[email protected]>

Similarly to rte_malloc, rte_gpu_mem_alloc accept as input the memory alignment size.

GPU driver should return GPU memory address aligned with the input value.

Changelog:
- rte_gpu_mem_alloc parameters order

---
 lib/gpudev/gpudev.c        | 10 ++++++++--
 lib/gpudev/gpudev_driver.h |  2 +-
 lib/gpudev/rte_gpudev.h    | 10 +++++++---
 3 files changed, 16 insertions(+), 6 deletions(-)
lib/gpudev/gpudev.c +8 -2
index 9ae36dbae9..59e2169292 100644
@@ -527,7 +527,7 @@ rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info)
 }
 
 void *
-rte_gpu_mem_alloc(int16_t dev_id, size_t size)
+rte_gpu_mem_alloc(int16_t dev_id, size_t size, unsigned int align)
 {
 	struct rte_gpu *dev;
 	void *ptr;
@@ -549,7 +549,13 @@ rte_gpu_mem_alloc(int16_t dev_id, size_t size)
 	if (size == 0) /* dry-run */
 		return NULL;
 
-	ret = dev->ops.mem_alloc(dev, size, &ptr);
+	if (align && !rte_is_power_of_2(align)) {
+		GPU_LOG(ERR, "requested alignment is not a power of two %u", align);
+		rte_errno = EINVAL;
+		return NULL;
+	}
+
+	ret = dev->ops.mem_alloc(dev, size, align, &ptr);
 
 	switch (ret) {
 	case 0:
lib/gpudev/gpudev_driver.h +1 -1
index cb7b101f2f..0ed7478e9b 100644
@@ -27,7 +27,7 @@ enum rte_gpu_state {
 struct rte_gpu;
 typedef int (rte_gpu_close_t)(struct rte_gpu *dev);
 typedef int (rte_gpu_info_get_t)(struct rte_gpu *dev, struct rte_gpu_info *info);
-typedef int (rte_gpu_mem_alloc_t)(struct rte_gpu *dev, size_t size, void **ptr);
+typedef int (rte_gpu_mem_alloc_t)(struct rte_gpu *dev, size_t size, unsigned int align, void **ptr);
 typedef int (rte_gpu_mem_free_t)(struct rte_gpu *dev, void *ptr);
 typedef int (rte_gpu_mem_register_t)(struct rte_gpu *dev, size_t size, void *ptr);
 typedef int (rte_gpu_mem_unregister_t)(struct rte_gpu *dev, void *ptr);
lib/gpudev/rte_gpudev.h +7 -3
index fa3f3aad4f..9e2e2c5dce 100644
@@ -364,18 +364,22 @@ int rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info);
  * @param size
  *   Number of bytes to allocate.
  *   Requesting 0 will do nothing.
- *
+ * @param align
+ *   If 0, the return is a pointer that is suitably aligned for any kind of
+ *   variable (in the same manner as malloc()).
+ *   Otherwise, the return is a pointer that is a multiple of *align*. In
+ *   this case, it must obviously be a power of two.
  * @return
  *   A pointer to the allocated memory, otherwise NULL and rte_errno is set:
  *   - ENODEV if invalid dev_id
- *   - EINVAL if reserved flags
+ *   - EINVAL if align is not a power of two
  *   - ENOTSUP if operation not supported by the driver
  *   - E2BIG if size is higher than limit
  *   - ENOMEM if out of space
  *   - EPERM if driver error
  */
 __rte_experimental
-void *rte_gpu_mem_alloc(int16_t dev_id, size_t size)
+void *rte_gpu_mem_alloc(int16_t dev_id, size_t size, unsigned int align)
 __rte_alloc_size(2);
 
 /**
Signature · 1 line
2.17.1
#9 lore raw

PATCH v2 2/3 app/test-gpudev: test aligned memory allocation

From: Elena Agostini <[email protected]>

Update gpudev app to test GPU memory aligned allocation.

---
 app/test-gpudev/main.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
app/test-gpudev/main.c +10 -3
index 5c1aa3d52f..f36f46cbca 100644
@@ -69,11 +69,12 @@ alloc_gpu_memory(uint16_t gpu_id)
 	void *ptr_2 = NULL;
 	size_t buf_bytes = 1024;
 	int ret;
+	unsigned align = 4096;
 
 	printf("\n=======> TEST: Allocate GPU memory\n\n");
 
-	/* Alloc memory on GPU 0 */
-	ptr_1 = rte_gpu_mem_alloc(gpu_id, buf_bytes);
+	/* Alloc memory on GPU 0 without any specific alignment */
+	ptr_1 = rte_gpu_mem_alloc(gpu_id, buf_bytes, 0);
 	if (ptr_1 == NULL) {
 		fprintf(stderr, "rte_gpu_mem_alloc GPU memory returned error\n");
 		goto error;
@@ -81,7 +82,8 @@ alloc_gpu_memory(uint16_t gpu_id)
 	printf("GPU memory allocated at 0x%p size is %zd bytes\n",
 			ptr_1, buf_bytes);
 
-	ptr_2 = rte_gpu_mem_alloc(gpu_id, buf_bytes);
+	/* Alloc memory on GPU 0 with 4kB alignment */
+	ptr_2 = rte_gpu_mem_alloc(gpu_id, buf_bytes, align);
 	if (ptr_2 == NULL) {
 		fprintf(stderr, "rte_gpu_mem_alloc GPU memory returned error\n");
 		goto error;
@@ -89,6 +91,11 @@ alloc_gpu_memory(uint16_t gpu_id)
 	printf("GPU memory allocated at 0x%p size is %zd bytes\n",
 			ptr_2, buf_bytes);
 
+	if (((uintptr_t)ptr_2) % align) {
+		fprintf(stderr, "Memory address 0x%p is not aligned to %u\n", ptr_2, align);
+		goto error;
+	}
+
 	ret = rte_gpu_mem_free(gpu_id, (uint8_t *)(ptr_1)+0x700);
 	if (ret < 0) {
 		printf("GPU memory 0x%p NOT freed: GPU driver didn't find this memory address internally.\n",
Signature · 1 line
2.17.1
#10 lore raw

PATCH v2 3/3 gpu/cuda: mem alloc aligned memory

In reply to [email protected]

From: Elena Agostini <[email protected]>

Implement aligned GPU memory allocation in GPU CUDA driver.

Changelog:
- cuda_mem_alloc parameters order

---
 drivers/gpu/cuda/cuda.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/gpu/cuda/cuda.c +16 -5
index 882df08e56..dc8d3d3b5a 100644
@@ -139,8 +139,10 @@ typedef uintptr_t cuda_ptr_key;
 /* Single entry of the memory list */
 struct mem_entry {
 	CUdeviceptr ptr_d;
+	CUdeviceptr ptr_orig_d;
 	void *ptr_h;
 	size_t size;
+	size_t size_orig;
 	struct rte_gpu *dev;
 	CUcontext ctx;
 	cuda_ptr_key pkey;
@@ -569,7 +571,7 @@ cuda_dev_info_get(struct rte_gpu *dev, struct rte_gpu_info *info)
  */
 
 static int
-cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
+cuda_mem_alloc(struct rte_gpu *dev, size_t size, unsigned int align, void **ptr)
 {
 	CUresult res;
 	const char *err_string;
@@ -610,8 +612,10 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 
 	/* Allocate memory */
 	mem_alloc_list_tail->size = size;
-	res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_d),
-			mem_alloc_list_tail->size);
+	mem_alloc_list_tail->size_orig = size + align;
+
+	res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d),
+			mem_alloc_list_tail->size_orig);
 	if (res != 0) {
 		pfn_cuGetErrorString(res, &(err_string));
 		rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
@@ -620,6 +624,13 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 		return -rte_errno;
 	}
 
+
+	/* Align memory address */
+	mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d;
+	if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align)
+		mem_alloc_list_tail->ptr_d += (align -
+				(((uintptr_t)mem_alloc_list_tail->ptr_d) % align));
+
 	/* GPUDirect RDMA attribute required */
 	res = pfn_cuPointerSetAttribute(&flag,
 			CU_POINTER_ATTRIBUTE_SYNC_MEMOPS,
@@ -634,7 +645,6 @@ cuda_mem_alloc(struct rte_gpu *dev, size_t size, void **ptr)
 
 	mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_d);
 	mem_alloc_list_tail->ptr_h = NULL;
-	mem_alloc_list_tail->size = size;
 	mem_alloc_list_tail->dev = dev;
 	mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
 	mem_alloc_list_tail->mtype = GPU_MEM;
@@ -761,6 +771,7 @@ cuda_mem_register(struct rte_gpu *dev, size_t size, void *ptr)
 	mem_alloc_list_tail->dev = dev;
 	mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
 	mem_alloc_list_tail->mtype = CPU_REGISTERED;
+	mem_alloc_list_tail->ptr_orig_d = mem_alloc_list_tail->ptr_d;
 
 	/* Restore original ctx as current ctx */
 	res = pfn_cuCtxSetCurrent(current_ctx);
@@ -796,7 +807,7 @@ cuda_mem_free(struct rte_gpu *dev, void *ptr)
 	}
 
 	if (mem_item->mtype == GPU_MEM) {
-		res = pfn_cuMemFree(mem_item->ptr_d);
+		res = pfn_cuMemFree(mem_item->ptr_orig_d);
 		if (res != 0) {
 			pfn_cuGetErrorString(res, &(err_string));
 			rte_cuda_log(ERR, "cuMemFree current failed with %s",
Signature · 1 line
2.17.1
#11 lore raw

Re: [PATCH v2 1/3] gpudev: mem alloc aligned memory

In reply to [email protected]

08/01/2022 01:20, [email protected]:

Quoted 5 lines

From: Elena Agostini <[email protected]>

Similarly to rte_malloc, rte_gpu_mem_alloc accept as input the memory alignment size.

Quoted 7 lines

GPU driver should return GPU memory address aligned with the input value.

Changelog:
- rte_gpu_mem_alloc parameters order

Squashed and applied, thanks.