web-dev-qa-db-de.com

Warum _mm_malloc verwenden? (im Gegensatz zu _aligned_malloc, alligned_alloc oder posix_memalign)

Es gibt einige Optionen für den Erwerb eines ausgerichteten Speicherblocks, die jedoch sehr ähnlich sind. Das Problem hängt hauptsächlich davon ab, auf welche Sprachstandards und Plattformen Sie abzielen.

C11

void * aligned_alloc (size_t alignment, size_t size)

POSIX

int posix_memalign (void **memptr, size_t alignment, size_t size)

Windows

void * _aligned_malloc(size_t size, size_t alignment);

Natürlich ist es auch immer möglich, von Hand auszurichten.

Intel bietet eine weitere Option.

Intel

void* _mm_malloc (int size, int align)
void _mm_free (void *p)

Basierend auf dem von Intel veröffentlichten Quellcode scheint dies die Methode zu sein, die die Ingenieure bevorzugen, um den ausgerichteten Speicher zuzuweisen, aber ich kann keine Dokumentation finden, die ihn mit anderen Methoden vergleicht. Das nächste, das ich gefunden habe, bestätigt einfach, dass andere ausgerichtete Speicherzuweisungsroutinen existieren.

https://software.intel.com/de-de/articles/memory-management-for-optimal-performance-on-intel-xeon-phi-coprocessor-alignment-and

Verwenden Sie posix_memalign, das sowohl von GCC als auch vom Intel Compiler unterstützt wird, um einen Teil des ausgerichteten Speichers dynamisch zuzuweisen. Der Vorteil der Verwendung besteht darin, dass Sie die Speicherentsorgungs-API nicht ändern müssen. Sie können free () wie immer verwenden. Beachten Sie jedoch das Parameterprofil:

int posix_memalign (void ** memptr, size_t align, size_t size);

Der Intel Compiler bietet auch einen weiteren Satz von Speicherzuweisungs-APIs. C/C++ - Programmierer können _mm_malloc und _mm_free verwenden, um ausgerichtete Speicherblöcke zuzuweisen und freizugeben. Die folgende Anweisung fordert beispielsweise einen mit 64 Byte ausgerichteten Speicherblock für 8 Gleitkommaelemente an.

farray = (float *) __ mm_malloc (8 * sizeof (float), 64);

Speicher, der mit _mm_malloc zugewiesen wird, muss mit _mm_free freigegeben werden. Das Aufrufen von "free" für den mit _mm_malloc zugewiesenen Speicher oder das Aufrufen von "_mm_free" für den mit malloc zugewiesenen Speicher führt zu unvorhersehbarem Verhalten.

Der deutliche Unterschied aus Anwendersicht besteht darin, dass _mm_malloc Direkte CPU- und Compiler-Unterstützung erfordert und der mit _mm_malloc Zugewiesene Speicher mit _mm_free Freigegeben werden muss. Was ist in Anbetracht dieser Nachteile der Grund für die Verwendung von _mm_malloc?? Kann dies einen leichten Leistungsvorteil haben? Historischer Unfall?

28
Praxeolitic

Intel-Compiler unterstützen POSIXLinux) und Nicht-POSIX- (Windows) Betriebssysteme und können sich daher weder auf die POSIX- noch auf die Windows-Funktion verlassen. Daher wurde eine compilerspezifische, aber betriebssystemunabhängige Lösung gewählt.

C11 ist eine großartige Lösung, aber Microsoft unterstützt C99 noch nicht einmal. Wer weiß, ob C11 jemals unterstützt wird?.

--- (Update: Im Gegensatz zu den Zuweisungsfunktionen von C11/POSIX/Windows enthalten die ICC-Eigenschaften eine Aufhebungsfunktion. Auf diese Weise kann diese API einen anderen als den Standard-Heap-Manager verwenden. Ich weiß nicht, ob/wann es das tatsächlich tut, aber es kann nützlich sein, dieses Modell zu unterstützen.

Haftungsausschluss: Ich arbeite für Intel, habe jedoch keine besonderen Kenntnisse über diese Entscheidungen, die lange vor meinem Eintritt in das Unternehmen getroffen wurden.

26
Jeff

Es ist möglich, einen vorhandenen C-Compiler zu verwenden, der derzeit nicht die Bezeichner _mm_alloc Und _mm_free Verwendet, und Funktionen mit den Namen zu definieren, die sich wie erforderlich verhalten. Dies kann entweder dadurch geschehen, dass _mm_alloc Als Wrapper für malloc() fungiert, der nach einer geringfügig übergroßen Zuordnung fragt und einen Zeiger auf die erste entsprechend ausgerichtete Adresse innerhalb dieser Adresse erstellt, die mindestens eine ist Byte von Anfang an speichern und die Anzahl der unmittelbar vor dieser Adresse übersprungenen Bytes speichern, oder indem _mm_malloc große Speicherbereiche von malloc() anfordert und diese dann stückweise ausgibt. In jedem Fall wären die von _mm_malloc() zurückgegebenen Zeiger keine Zeiger, mit denen free() im Allgemeinen etwas anfangen kann. Das Aufrufen von _mm_free würde das Byte unmittelbar vor der Zuweisung als Hilfe zum Auffinden des tatsächlichen Starts der Zuweisung verwenden, die von malloc empfangen wurde, und dann das do free übergeben.

Wenn eine Aligned-Allocate-Funktion die Interna der Funktionen malloc und free verwenden darf, ist möglicherweise kein zusätzlicher Wrapping-Layer erforderlich. Es ist möglich, _mm_alloc()/_mm_free() Funktionen zu schreiben, die malloc/free umbrechen, ohne etwas über ihre Interna zu wissen, aber es erfordert _mm_alloc() Buchhaltungsinformationen getrennt von den von malloc/free verwendeten aufbewahren.

Wenn der Autor einer Aligned-Allocation-Funktion weiß, wie malloc und free implementiert sind, ist es häufig möglich, das Design aller Allocation-/Free-Funktionen so zu koordinieren, dass free kann alle Arten von Zuordnungen unterscheiden und entsprechend behandeln. Es wäre jedoch keine einzelne Implementierung mit ausgerichteter Zuweisung für alle malloc/free Implementierungen verwendbar.

Ich würde vorschlagen, dass der portabelste Weg, Code zu schreiben, wahrscheinlich darin besteht, ein paar Symbole auszuwählen, die nirgendwo anders für Ihre eigenen Zuweisungs- und freien Funktionen verwendet werden, so dass Sie dann sagen könnten, z.

#define a_alloc(align,sz) _mm_alloc((align),(sz))
#define a_free(ptr)  _mm_free((ptr))

auf Compilern, die das unterstützen, oder

static inline void *aa_alloc(int align, int size)
{
  void *ret=0;
  posix_memalign(&ret, align, size); // Guessing here
  return ret;
}
#define a_alloc(align,sz) aa_alloc((align),(sz))
#define a_free(ptr)  free((ptr))

auf Posix-Systemen usw. Für jedes System sollte es möglich sein, Makros oder Funktionen zu definieren, die das erforderliche Verhalten ergeben. [Ich denke, es ist wahrscheinlich besser, Makros konsistent zu verwenden, als manchmal Makros und manchmal Funktionen zu verwenden, um #if defined macroname Um zu testen, ob die Dinge noch definiert sind].

5
supercat

_mm_malloc wurde anscheinend erstellt, bevor es eine standardmäßige aligned_alloc-Funktion gab, und die Notwendigkeit, _mm_free zu verwenden, ist eine Besonderheit der Implementierung.

Ich vermute, dass im Gegensatz zu posix_memalign keine Überbelegung erforderlich ist, um die Ausrichtung zu gewährleisten. Stattdessen wird ein separater Belegungsplan verwendet, der die Ausrichtung berücksichtigt. Dadurch wird Speicherplatz gespart, wenn Typen zugewiesen werden, deren Ausrichtung von der Standardausrichtung abweicht (normalerweise 8 oder 16 Byte).

4
Thief