{"id":1208,"date":"2012-03-27T18:26:10","date_gmt":"2012-03-27T17:26:10","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=1208"},"modified":"2012-04-09T16:57:55","modified_gmt":"2012-04-09T15:57:55","slug":"faster-code-part-3-align-memory","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=1208","title":{"rendered":"Faster Code - Part 3 - align memory"},"content":{"rendered":"<p>Variablen deren Adressen ein vielfaches von 4Byte (oder 8Byte auf 64Bit???) sind, k\u00f6nnen schneller aus dem RAM geladen werden. Man sollte also bei oft benutzen Variablen darauf achten und nicht nur blind der Compiler Optimierung vertrauen. Gerade bei Sachen wie SSE ist es gut, wenn die Array Elemente auf 16Byte ausgerichtet sind, da ein SSE Register 128Bit breit ist.<\/p>\n<p>Der GNU Compiler hat ein spezielles Attribut f\u00fcr Variablen [1]. <\/p>\n<p>Hier die Funktion die anzeigt, auf wieviel Byte eine Variable ausgerichtet ist:<\/p>\n<pre><code>\r\nvoid multipleOf(void* p) {\r\n  cout << (size_t)p << \" multiple of\";\r\n  if((size_t)p % 2 == 0)\r\n    cout << \" 2 \";\r\n  if((size_t)p % 4 == 0)\r\n    cout << \" 4 \";\r\n  if((size_t)p % 8 == 0)\r\n    cout << \" 8 \";\r\n  if((size_t)p % 16 == 0)\r\n    cout << \" 16 \";\r\n  if((size_t)p % 32 == 0)\r\n    cout << \" 32 \";\r\n  cout << endl;\r\n}\r\n<\/code><\/pre>\n<p>Und hier ein paar Beispiele.<\/p>\n<pre><code>\r\n  char unalign;\r\n  char __attribute__ ((aligned (4))) align;\r\n  multipleOf(&unalign);\r\n  multipleOf(&align);\r\n<\/code>\r\n140736773522255 multiple of\r\n140736773522252 multiple of 2  4 \r\n<\/pre>\n<p>Die erste Zahl ist immer die Adresse der Variable in Dezimal, damit man besser Kopfrechnen kann. Wie man sieht hat die Variable unalign eine ungerade Adresse -> nicht gut. Aber mit dem aligned Attribut kann man das schnell \u00e4ndern :).<\/p>\n<p>Soweit ich wei\u00df haben int, long, float, double u.s.w. immer mindestens ein align von 4.<\/p>\n<p>Aber wie sieht das mit den Adressen einzelner Arrayelemente aus?<\/p>\n<pre><code>\r\n  struct  Point {\r\n  float x, y, z;\r\n  };\r\n\r\n  cout << \"sizeof Point \" << sizeof(Point) << endl;\r\n  Point p[4];\r\n  multipleOf(p);\r\n  multipleOf(p+1);\r\n  multipleOf(p+2);\r\n  multipleOf(p+3);\r\n<\/code>\r\nsizeof Point 12\r\n140733340474464 multiple of 2  4  8  16  32 \r\n140733340474476 multiple of 2  4 \r\n140733340474488 multiple of 2  4  8 \r\n140733340474500 multiple of 2  4 \r\n<\/pre>\n<p>Das n\u00e4chste Array Element ist immer 12Byte weiter. So ist die Sache zwar noch auf 4Byte ausgerichtet, aber nicht auf 16Byte wie das f\u00fcr SSE sch\u00f6n w\u00e4re. Hier die L\u00f6sung:<\/p>\n<pre><code>\r\n  struct  __attribute__ ((aligned (32))) Point {\r\n  float x, y, z;\r\n  };\r\n<\/code>\r\nsizeof Point 16\r\n140736307878992 multiple of 2  4  8  16 \r\n140736307879008 multiple of 2  4  8  16  32 \r\n140736307879024 multiple of 2  4  8  16 \r\n140736307879040 multiple of 2  4  8  16  32 \r\n<\/pre>\n<p>In diesem Fall h\u00e4tte man auch einfach eine vierte Variable \"w\" in das Strukt einf\u00fcgen k\u00f6nnen. Aber ich denke die Ausrichtung in Bytes manuell angeben ist besser. Es steht n\u00e4mlich niergends geschrieben, dass ein float auch 4Byte hat. Zum Beispiel hat ein int auf einer 64Bit Maschine unter Linux noch 32Bit aber unter Windows 64Bit. Das gibt b\u00f6se Fehler.<\/p>\n<p>[1] http:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Type-Attributes.html<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Variablen deren Adressen ein vielfaches von 4Byte (oder 8Byte auf 64Bit???) sind, k\u00f6nnen schneller aus dem RAM geladen werden. Man sollte also bei oft benutzen Variablen darauf achten und nicht nur blind der Compiler Optimierung vertrauen. Gerade bei Sachen wie SSE ist es gut, wenn die Array Elemente auf 16Byte ausgerichtet sind, da ein SSE [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[14,17,31,18],"class_list":["post-1208","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-c","tag-cpp","tag-faster-code","tag-linux"],"_links":{"self":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1208","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1208"}],"version-history":[{"count":12,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1208\/revisions"}],"predecessor-version":[{"id":1335,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1208\/revisions\/1335"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1208"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1208"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}