OSX carece de memalign

5 minutos de lectura

avatar de usuario
usuario17925

Estoy trabajando en un proyecto en C y requiere memalign(). Realmente, posix_memalign() también funcionaría, pero darwin/OSX carece de ambos.

¿Cuál es una buena solución para memalign con calzador? No entiendo la licencia para el código posix-C si tuviera que copiar memalign.c y ponerlo en mi proyecto. No quiero ninguna licencia de tipo viral LGPL para todo mi proyecto.

  • actualización: OSX ahora tiene posix_memalign(). Consulte stackoverflow.com/a/22876707/558639

    – sin miedo_tonto

    26 de noviembre de 2016 a las 14:51

Mac OS X parece ser memoria de 16 bytes alineada.

Cita del sitio web:

Tuve dificultades para encontrar una declaración definitiva sobre la alineación de la memoria de MacOS X, así que hice mis propias pruebas. En 10.4/Intel, tanto la memoria de pila como la de almacenamiento dinámico están alineadas en 16 bytes. Entonces, las personas que transfieren software pueden dejar de buscar memalign() y posix_memalign(). No es necesario.

  • SSE garantiza esto en x86: Malloc tiene que devolver un puntero a la memoria adecuadamente alineado para cualquier tipo de objeto, que en x86 incluye vectores SSE (que requieren una alineación de 16 bytes)

    mike f

    13 de octubre de 2008 a las 0:33

  • Es posible que desee una alineación más grande por otras razones. Una línea de caché (potencialmente alineación de 64 bytes) es un ejemplo de esto.

    – robbie_c

    28 de noviembre de 2012 a las 14:02

  • Tenga en cuenta que OS X hace tener posix_memalign, útil (por ejemplo) para alinear los límites de la página o compilar bibliotecas AXV. Consulte stackoverflow.com/a/22876707/558639

    – sin miedo_tonto

    7 de enero de 2015 a las 4:33


avatar de usuario
sin miedo

actualización: OSX ahora tiene posix_memalign()

Llega tarde a la fiesta, pero versiones más nuevas de OSX hacer tener posix_memalign(). Es posible que desee esto cuando se alinea con los límites de la página. Por ejemplo:

#include <stdlib.h>

char *buffer;
int pagesize;

pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1) handle_error("sysconf");

if (posix_memalign((void **)&buffer, pagesize, 4 * pagesize) != 0) {
  handle_error("posix_memalign");
}

Una cosa a tener en cuenta es que, a diferencia de memalign(), posix_memalign() acepta **buffer como argumento y devuelve un código de error entero.

  • ¡Gracias! Funciona para mi. Lo necesito porque AVX requiere una alineación de 32 bytes, no de 16 bytes.

    – bram

    5 de enero de 2015 a las 3:32

Debería ser bastante fácil de hacer usted mismo, ¿no? Algo como lo siguiente (no probado):

void *aligned_malloc( size_t size, int align )
{
    void *mem = malloc( size + (align-1) + sizeof(void*) );

    char *amem = ((char*)mem) + sizeof(void*);
    amem += align - ((uintptr)amem & (align - 1));

    ((void**)amem)[-1] = mem;
    return amem;
}

void aligned_free( void *mem )
{
    free( ((void**)mem)[-1] );
}

(gracias Jonathan Leffler)

Editar:
Con respecto a estafar otra implementación de memalign, el problema con eso no es la licencia. Más bien, se encontraría con la dificultad de que cualquier buena implementación de memalign será una parte integral de la base de código del administrador de heap, no simplemente superpuesta a malloc/free. Por lo tanto, tendría serios problemas para trasplantarlo a un administrador de montón diferente, especialmente cuando no tiene acceso a sus partes internas.

  • Debajo de la llamada malloc, debe agregar if(!mem) return NULL;.

    – Martín B.

    28 de enero de 2011 a las 13:45


  • Su implementación de aligned_free fallará si mem es NULL. Desde el página man: “Si ptr es un puntero NULL, no se realiza ninguna operación”.

    – robbie_c

    28 de noviembre de 2012 a las 13:24


  • amem += alinear – ((uinptr_t)amem & (alinear – 1)); debe ser amem += (align – ((uintptr_t)amem & (align – 1)) & (align-1)); El código actual desperdiciará bytes de alineación si amem ya estaba correctamente alineado. (y desbordará el búfer devuelto)

    – Cholesky

    14 de abril de 2013 a las 23:18


  • Si align = 1, creo que este código se desbordará.

    – Daniel Lemire

    28 de diciembre de 2015 a las 17:39

¿Por qué el software que está transfiriendo necesita memalign() o posix_memalign()? ¿Lo usa para alineaciones más grandes que las alineaciones de 16 bytes a las que hace referencia austirg?

Veo que Mike F publicó un código: se ve relativamente ordenado, aunque creo que el ciclo while puede ser subóptimo (si la alineación requerida es de 1 KB, podría repetirse varias veces).

No:

amem += align - ((uintptr)amem & (align - 1));

llegar allí en una sola operación?

Sí Mac OS X tiene alineación de memoria de 16 bytes en el ITB. No debería necesitar usar memalign(). Si sus requisitos de memoria son un factor de 16, entonces no lo implementaría y tal vez solo agregaría una afirmación.

  • ¿Por qué todos asumen que el tipo solo necesita una alineación de 16 bytes?

    mike f

    13 de octubre de 2008 a las 0:39

avatar de usuario
paxos1977

De las páginas man de macosx:

Las funciones malloc(), calloc(), valloc(), realloc() y reallocf() asignan memoria. La memoria asignada está alineada de manera que se puede usar para cualquier tipo de datos, incluidos los tipos relacionados con AltiVec y SSE. La función free() libera las asignaciones que se crearon a través de las funciones de asignación anteriores.

  • ¿Por qué todos asumen que el tipo solo necesita una alineación de 16 bytes?

    mike f

    13 de octubre de 2008 a las 0:39

avatar de usuario
Shikari oscuro

Si necesita un malloc alineado arbitrariamente, consulte el malloc de x264 (common/common.c en el repositorio de git), que tiene un memalign personalizado para sistemas sin malloc.h. Es un código extremadamente trivial, hasta el punto de que ni siquiera lo consideraría protegido por derechos de autor, pero debería poder implementar fácilmente el suyo propio después de verlo.

Por supuesto, si solo necesita una alineación de 16 bytes, como se indicó anteriormente, está en OS X ABI.

¿Ha sido útil esta solución?