{"id":1235,"date":"2012-03-30T21:42:18","date_gmt":"2012-03-30T20:42:18","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=1235"},"modified":"2012-04-09T16:57:41","modified_gmt":"2012-04-09T15:57:41","slug":"faster-code-%e2%80%93-part-5-huge-pages","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=1235","title":{"rendered":"Faster Code \u2013 Part 5 - huge pages"},"content":{"rendered":"<p>Tach und Willkommen beim f\u00fcnften Teil von Faster Code. Heute geht es um huge page. Eine Page ist normal 4kb gro\u00df. Eine hugepage hat 2MB, 4MB oder nocht viel mehr. Hoch zu 1GB. Je nach System, CPU u.s.w.<br \/>\nDie Gr\u00f6\u00dfe ermittelt man so:<\/p>\n<pre>$ grep Huge \/proc\/meminfo \r\nHugePages_Total:      46\r\nHugePages_Free:       46\r\nHugePages_Rsvd:        0\r\nHugePages_Surp:        0\r\nHugepagesize:       4096 kB\r\n<\/pre>\n<p>Wir haben also 4MB hugepage und es wurde 46 pages schon erstellt.  Man kann sie so vom System anfordern:<\/p>\n<pre># echo 46 > \/sys\/kernel\/mm\/hugepages\/hugepages-4096kB\/nr_hugepages<\/pre>\n<p>Es kann sein, dass man danach doch nicht 46 freie hugepages hat, da das System durch RAM Fragmentierung den angeforderten Speicher nicht am St\u00fcck liefern kann. Hier hilft es den Befehl mehrmals auszuf\u00fchren oder neu zu starten.<\/p>\n<p>Und wozu brauch man das nun?<br \/>\nNa um Translation Lookaside Buffer (TLB) misses zu verringern. Der TLB mappt eine virtuelle Adresse in eine physikalische Adresse um. Also so eine Art Cache der aber nur sehr sehr wenige Eintr\u00e4ge halten kann (daf\u00fcr ist er aber sehr schnell). Wenn man nun auf viele Adresse zugreift, die in Pages liegen die nah beinander liegen, dann l\u00e4uft der TLB schnell zu und bereits vorhandenen Eintr\u00e4ge werden \u00fcberschrieben. Fehlende Eintr\u00e4ge aus einem anderen Cache holen kostet Zeit und das wollen wir nicht.<br \/>\nWenn wir nun die Page gr\u00f6\u00dfer machen, liegen mehr Variablen in einer Page und der TLB muss sich weniger merken. Einleuchtend, nicht wahr? ;)<\/p>\n<p>Und wie nutzt man huge pages?<br \/>\nEs gibt verschiedene Methoden. \u00dcber das hugepagefs was ich aber umst\u00e4ndlich finde, weil man von Hand ein Filesystem noch mountern muss. Dann gibt es seit Kernel 2.6.38 die Transparent Huge Pages (THP). Hier wird der ganze Aufwand im Hintergrund gehalten und man bekommt als User garnichts mehr mit. Man muss auch nicht sein Code \u00e4nderen.<br \/>\nOb das System THP benutzt kann man kann man so erfahren<\/p>\n<pre>$ cat \/sys\/kernel\/mm\/transparent_hugepage\/enabled \r\nalways madvise [never]\r\n<\/pre>\n<p>In meinem Fall also nie. Wenn man sein Speicher normal \u00fcber malloc\/new anfordert, sollte man die Variable auf always stellen. Bei madvise muss noch irgendwo ein Flag \u00fcbergeben werden. Hab vergessen wo.<\/p>\n<p>Die dritte M\u00f6glichkeit ist seinen Speicher per mmap() zu bestellen. Das find ich am besten. Man hat dann mehr Kontrolle was in hugepages landet und was nicht. Hier ein Beispiel:<\/p>\n<pre><code>\r\n  #include < sys\/mman.h >\r\n\r\n  \/* Only ia64 requires this *\/ \r\n  #ifdef __ia64__\r\n  #define ADDR (void *)(0x8000000000000000UL)\r\n  #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED)\r\n  #else\r\n  #define ADDR (void *)(0x0UL)\r\n  #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)\r\n  #endif\r\n\r\n  \/\/ versuche speicher per mmap zu holen. wenn das fehlschlaegt nimm new oder valloc\r\n  void *addr = mmap(ADDR, anzKnoten * sizeof(t_knoten_minimal), PROT_READ | PROT_WRITE, FLAGS, 0, 0);\r\n  if (addr == MAP_FAILED) {\r\n    perror(\"mmap\");\r\n    knoten_minimal = new t_knoten_minimal[anzKnoten];\r\n  } else {\r\n    knoten_minimal = new (addr) t_knoten_minimal[anzKnoten];\r\n  }\r\n<\/code><\/pre>\n<p>Und hats was gebracht?<br \/>\nJein, ehr nein. Ich hatte kein Testfall wo der TLB der Flaschenhals ist. Ich hab immer recht schnell neue Daten aus dem RAM geholt und wenig mit ihnen gerechnet. Die Leitung zum RAM ist nat\u00fcrlich sehr viel langsamer als der TLB seine neuen Adressen bekommt. Darum gab es so gut wie kein Speedup.<br \/>\nAber ich werde in meinem n\u00e4chsten Code die M\u00f6glichkeit bereitstellen hugepages einfach zu nutzen. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tach und Willkommen beim f\u00fcnften Teil von Faster Code. Heute geht es um huge page. Eine Page ist normal 4kb gro\u00df. Eine hugepage hat 2MB, 4MB oder nocht viel mehr. Hoch zu 1GB. Je nach System, CPU u.s.w. Die Gr\u00f6\u00dfe ermittelt man so: $ grep Huge \/proc\/meminfo HugePages_Total: 46 HugePages_Free: 46 HugePages_Rsvd: 0 HugePages_Surp: 0 [&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-1235","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\/1235","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=1235"}],"version-history":[{"count":8,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1235\/revisions"}],"predecessor-version":[{"id":1333,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/1235\/revisions\/1333"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1235"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}