Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

control memory alignment in python ctypes

Tags:

python

ctypes

I'm looking into using ctypes for using C functions manipulating SSE (__m128) data that have to be aligned on 16 bytes boundaries.

I could not find a simple way to control the alignment of memory allocated by ctypes, so, right now, I'm making ctypes call a C function that provides a correctly aligned memory buffer.

The problem I have with this approach is that I have to manually explicitly release this memory to prevent it from being leaked.

Is there a way to control the alignment of memory allocated by ctypes ? or is there a way to register a cleanup function to release memory allocated by a C function called by ctypes (apart from standard python operator __del__) ?

What is the best path to follow ?

like image 385
rotoglup Avatar asked Dec 28 '11 16:12

rotoglup


2 Answers

I've been taking some time to investigate, I came up with a function that should allow me to allocate arbitrary aligned memory with ctypes, basically relying on the fact that ctypes should keep a reference on the unaligned memory buffer, while having an instance starting at an aligned position in the buffer.

Still have to test this in production.

import ctypes

def ctypes_alloc_aligned(size, alignment):

  bufSize = size+(alignment-1)
  raw_memory = bytearray(bufSize)

  ctypes_raw_type = (ctypes.c_char * bufSize)
  ctypes_raw_memory = ctypes_raw_type.from_buffer(raw_memory)

  raw_address = ctypes.addressof(ctypes_raw_memory)
  offset = raw_address % alignment
  offset_to_aligned = (alignment - offset) % alignment

  ctypes_aligned_type = (ctypes.c_char * (bufSize-offset_to_aligned))
  ctypes_aligned_memory = ctypes_aligned_type.from_buffer(raw_memory, offset_to_aligned)

  return ctypes_aligned_memory
like image 168
rotoglup Avatar answered Sep 27 '22 19:09

rotoglup


I suppose that c_ulonglong (64 bit) must be 64-bit aligned; it's a start. Then the doc suggests that you can use _pack_ to control alignment of structures. These two are not exactly what you want, but by combining them you can allocate 8-byte aligned structs without holes.

Let's assume a struct with with 3 8-byte aligned elements .v0, .v1, .v2. Use addressof() to see if the struct is 16-byte aligned. If it is, use .v0 and .v1 for your 128-bit value; if it's not, use .v1 and .v2.

like image 24
9000 Avatar answered Sep 27 '22 21:09

9000