OVH Cloud OVH Cloud

operator new et posix_memalign

1 réponse
Avatar
Sébastien BIGOT [CEA]
Bonjour,
je débute en C++ et j'ai besoin d'obtenir de la memoire alignée sur les
limites de 16 octets.
(pour pouvoir utiliser les instructions sse2 type movaps sur x86, dans
des routines assembleurs)

Pour ce faire, je surcharge new et delete de cette facon :

using std::new_handler;
using std::set_new_handler;
using std::bad_alloc;
using std::abort;
using std::malloc;
using std::size_t;

void *operator new(size_t size) throw(bad_alloc){
const size_t boundary = 16;

if(0 == size)
size = 1;

#if HAVE_POSIX_MEMALIGN

void *p;

while(posix_memalign(&p,boundary,size)){

new_handler handler = set_new_handler(0);

if (! handler) {
throw bad_alloc();
}

handler ();
std::set_new_handler(handler);
}
return p;

#else

size_t sz = size + boundary - 1 + sizeof(void*);
void *p = malloc(sz);

while(!p) {

new_handler handler = set_new_handler(0);

if (! handler) {
throw bad_alloc();
}

handler ();
set_new_handler(handler);
p = malloc(sz);
}

size_t pp = (size_t)p;
pp = (pp + boundary - 1 + sizeof(void*)) & ~(boundary - 1) ;
*(((void**)pp) - 1) = p;

return (void *)pp;

#endif//HAVE_POSIX_MEMALIGN

}

void operator delete(void *p) {
#if HAVE_POSIX_MEMALIGN
free(p);
#else
free(*(((void**)p) - 1));
#endif
}


La méthode "manuelle" pour obtenir de la mémoire alignée sur 16 octets
fonctionne. Par contre, la méthode utilisant posix_memalign segfault
invariablement.

Voici ce que me dit gdb :
#0 0x42076c9e in arena_get2 () from /lib/tls/libc.so.6
#1 0x4207373a in memalign () from /lib/tls/libc.so.6
#2 0x42075911 in posix_memalign () from /lib/tls/libc.so.6
#3 0x08111cea in operator new(unsigned) ()

Quand j'utilise posix_memalign dans du code C, je ne rencontre aucun
problème de ce type.

Je comprendrai que ce post soit limite HS mais quelqu'un ayant un peu
plus d'XP pourrait-il m'aider ?

Bien à vous,
Sébastien

__

Je suis à la recherche d'un premier emploi !
CV : http://wwwetu.utc.fr/~bigotseb/cv_sebastien_bigot_2005.pdf

1 réponse

Avatar
Bernie
je débute en C++ et j'ai besoin d'obtenir de la memoire alignée sur les
limites de 16 octets.
Pour ce faire, je surcharge new et delete de cette facon :

La méthode "manuelle" pour obtenir de la mémoire alignée sur 16 octets
fonctionne. Par contre, la méthode utilisant posix_memalign segfault
invariablement.




Je ne repondrais que partiellement à ta question puisque je ne connais
pas "posix_memalign" et donc je ne pourrais pas te donner de raisons
potentielles au plantage observé lors de l'usage par le biais de la
surcharge des opérateurs.

par contre, si tu veux du code portable pour allouer des zone correct
pour le SIMD intel ou autre, il y a le code suivant. Pour ces 3 routines
merci à Avery Lee(VirtualDub).

void *aligned_malloc(size_t size, size_t alignment)
{
void *p = malloc(size + alignment - 1 + sizeof(void *));
void **p2 = (void **)(((long)p + sizeof(void *) + alignment - 1) &
~(alignment-1));

p2[-1] = p;

return p2;
}

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

void *aligned_realloc(void* data, size_t size, size_t alignment)
{
void *p = realloc(((void **)data)[-1], size + alignment - 1 +
sizeof(void *));
void **p2 = (void **)(((long)p + sizeof(void *) + alignment - 1) &
~(alignment-1));

p2[-1] = p;

return p2;
}