(fournir les informations dont vous avez besoin pour comprendre ma question, c'est beaucoup, mais c'est déjà compressé)
J'essaie d'implémenter un modèle de classe pour allouer et accéder au cache de données aligné. Cela fonctionne très bien, mais l'implémentation de la prise en charge des tableaux pose problème.
Sémantiquement, le code doit fournir ce mappage en mémoire pour un seul élément comme celui-ci :
cache_aligned<element_type>* my_el =
new(cache_line_size) cache_aligned<element_type>();
| element | buffer |
l'accès (jusqu'à présent) ressemble à ceci :
*my_el; // returns cache_aligned<element_type>
**my_el; //returns element_type
*my_el->member_of_element();
CEPENDANT, pour un tableau, j'aimerais avoir ceci :
cache_aligned<element_type>* my_el_array =
new(cache_line_size) cache_aligned<element_type()[N];
| element 0 | buffer | element 1 | buffer | ... | element (N-1) | buffer |
Pour l'instant, j'ai le code suivant
template <typename T>
class cache_aligned {
private:
T instance;
public:
cache_aligned()
{}
cache_aligned(const T& other)
:instance(other.instance)
{}
static void* operator new (size_t size, uint c_line_size) {
return c_a_malloc(size, c_line_size);
}
static void* operator new[] (size_t size, uint c_line_size) {
int num_el = (size - sizeof(cache_aligned<T>*)
/ sizeof(cache_aligned<T>);
return c_a_array(sizeof(cache_aligned<T>), num_el, c_line_size);
}
static void operator delete (void* ptr) {
free_c_a(ptr);
}
T* operator-> () {
return &instance;
}
T& operator * () {
return instance;
}
};
les fonctions cache_aligned_malloc
void* c_a_array(uint size, ulong num_el, uint c_line_size) {
void* mem = malloc((size + c_line_size) * num_el + sizeof(void*));
void** ptr = (void**)((long)mem + sizeof(void*));
ptr[-1] = mem;
return ptr;
}
void free_c_a(void ptr) {
free(((void**)ptr)[-1]);
}
Le problème est ici, l'accès aux données devrait fonctionner comme ceci :
my_el_array[i]; // returns cache_aligned<element_type>
*(my_el_array[i]); // returns element_type
my_el_array[i]->member_of_element();
Mes idées pour résoudre ce problème sont :
(1) quelque chose de similaire à ceci, pour surcharger l'opérateur sizeof :
static size_t operator sizeof () {
return sizeof(cache_aligned<T>) + c_line_size;
}
--> pas possible car la surcharge de l'opérateur sizeof est illégale
(2) quelque chose comme ceci, pour surcharger l'opérateur [] pour le type pointeur :
static T& operator [] (uint index, cache_aligned<T>* ptr) {
return ptr + ((sizeof(cache_aligned<T>) + c_line_size) * index);
}
--> pas possible en C++, de toute façon
(3) solution totalement triviale
template <typename T> cache_aligned {
private:
T instance;
bool buffer[CACHE_LINE_SIZE];
// CACHE_LINE_SIZE defined as macro
public:
// trivial operators and methods ;)
};
--> je ne sais pas si c'est fiable, en fait j'utilise gcc-4.5.1 sous linux ...
(4) Remplacer T instance ; par T* instance_ptr ; dans le modèle de classe et utiliser l'opérateur [] pour calculer la position de l'élément, comme ceci :
| pointeur-à-instance | ----> | élément 0 | tampon | ... | élément (N-1) | tampon |
ce n'est pas la sémantique prévue, puisque l'instance du modèle de classe devient le goulot d'étranglement lors du calcul de l'adresse des éléments.
Merci de m'avoir lu ! Je ne sais pas comment raccourcir le problème. Ce serait formidable si vous pouviez m'aider ! Toute solution de contournement m'aiderait beaucoup.
Je sais que l'alignement est une extension du C++0x. Cependant, dans gcc, il n'est pas encore disponible.
Greetz, sema