Transparent Memory Extension for Shared GPUs

Grafikkarten (Graphics Processing Units, GPUs) nehmen in der heutigen Informatik eine wichtige Rolle ein, da sie fur bestimmte Arten von Anwendungen grose Leistungsgewinne bei gleichzeitig hoher Energieeffizienz ermoglichen. Aus diesem Grund haben alle grosen Cloudanbieter in den letzten Jahren GPUs in ihre Angebote integriert. Die Plattformen dieser Anbieter verwenden ublicherweise Virtualisierung, um physische Ressourcen zwischen mehreren Kunden aufzuteilen. Dieses Aufteilen erhoht die Auslastung der Ressourcen und verschafft dem Cloudanbieter so einen Kostenvorteil gegenuber dedizierter physischer Hardware. Um die Auslastung noch weiter zu erhohen, vermieten heutige Cloudanbieter haufig mehr Ressourcen, als tatsachlich physisch zur Verfugung stehen. Fur den Fall, dass die Kunden die angebotenen Ressourcen tatsachlich vollstandig auslasten wollen, muss der Anbieter in diesem Fall aber in der Lage sein, das Funktionieren der Kundenanwendungen zu garantieren, selbst wenn der Ressourcenbedarf der Kunden die Kapazitat der physischen Ressourcen ubersteigt. Der Speicher aktueller Grafikkarten lasst sich vergleichsweise einfach zwischen mehreren Kunden aufteilen, da diese Grafikkarten virtuellen Speicher ahnlich dem der CPU unterstutzen. Der Anbieter kann so jedem Kunden einen grosen, virtuellen Adressraum zur Verfugung stellen, muss aber nur so viel physischen Speicher bereitstellen, wie die Kunden tatsachlich verwenden. Falls der Anbieter mehr Speicher anbieten will, als physisch vorhanden ist, ist es grundsatzlich auch moglich, im Fall einer Uberlastung des Grafikspeichers Daten in den Hauptspeicher des Systems auszulagern. Dieses Auslagern wird aber durch die asynchrone Arbeitsweise aktueller GPUs erschwert: Anwendungen konnen GPU-Kernels zur Ausfuhrung direkt an die GPU senden, ohne dafur das Betriebssystem aufrufen zu mussen. Das Betriebssystem hat so keine Kontrolle uber den Ausfuhrungszeitpunkt der GPU-Kernels. Daruber hinaus gehen aktuelle GPUs davon aus, dass samtlicher Grafikspeicher, der einmal von einer Anwendung angefordert wurde, jederzeit zuganglich ist. Sollte ein Kernel versuchen, auf eine nicht zugangliche Adresse zuzugreifen, behandelt die GPU diesen Zugriff als fatalen Fehler und beendet die Ausfuhrung des Kernels. Bisherige Ansatze umgehen dieses Problem, indem sie einen Software-Scheduler fur GPU-Kernels einsetzen, um die Kontrolle uber den Ausfuhrungszeitpunkt der Kernels zuruckzugewinnen. Bei dieser Methode wird nach Beendigung jedes Kernels der nachste Kernel auf der CPU in Software ausgewahlt und an die GPU gesendet. Sind Daten, auf die der nachste Kernel moglicherweise zugreift, von der GPU in den Hauptspeicher ausgelagert worden, kopiert der Scheduler diese Daten zuruck auf die GPU, bevor der Kernel gestartet wird. Der entscheidende Nachteil dieses Ansatzes ist, dass der Software-Scheduler das extrem effiziente interne Scheduling und Context Switching der GPU ersetzt, ohne das gleiche Mas an Effizienz zu erreichen. Ansatze, die auf Software-Scheduling basieren, verursachen daher einen hohen Overhead, und zwar auch dann, wenn eine ausreichende Menge Grafikspeicher zur Verfugung steht. Da der Scheduler daruber hinaus keine Moglichkeit hat, festzustellen, auf welche Daten ein GPU-Kernel tatsachlich zugreift, werden mit diesem Ansatz haufig Daten kopiert, die gar nicht benotigt werden. In der vorliegenden Arbeit entwickeln wir einen alternativen Ansatz, um Auslagern von GPU-Daten zu ermoglichen. Unser Auslagerungsmechanismus, genannt GPUswap, blendet alle ausgelagerten Daten direkt in den GPU-Adressraum der jeweiligen Anwendung ein. Da auf diese Art alle Daten jederzeit zuganglich sind, kann GPUswap den Anwendungen weiterhin erlauben, Kommandos direkt an die GPU zu senden. Da unser Ansatz ohne Software-Scheduling auskommt, verursacht GPUswap keinerlei Overhead, solange Grafikspeicher in ausreichender Menge zur Verfugung steht. Falls tatsachlich Daten in den Hauptspeicher ausgelagert werden mussen, eliminiert GPUswap auserdem unnotige Datentransfers zwischen Hauptspeicher und GPU, da nur ausgelagerte Daten, auf die Anwendung tatsachlich zugreift, uber den PCIe-Bus ubertragen werden. Auch wenn GPUswap im Vergleich zu vorherigen Ansatzen deutlich weniger Overhead verursacht, ist der Overhead, der durch die Verwendung von Hauptspeicher anstelle von Grafikspeicher verursacht wird, immer noch erheblich: Anwendungen greifen auf ausgelagerte Daten uber den PCIe-Bus zu, der uber eine erheblich geringere Bandbreite verfugt als der Grafikspeicher. Um diesen Overhead zu reduzieren, sollten bevorzugt Speicherseiten ausgelagert werden, auf die selten zugegriffen wird. Solche Seiten zu identifizieren ist auf aktuellen GPUs allerdings nicht ohne Weiteres moglich, da die Hardwarefunktionen, die auf der CPU zu diesen Zweck normalerweise eingesetzt werden – z.B. Referenzbits – auf aktuellenGPUs nicht zur Verfugung stehen. In der vorliegenden Arbeit verwenden wir stattdessen Profiling, um selten verwendete Speicherseiten zu identifizieren. Bisherige Ansatze zum Profiling von GPU-Speicher basierten auf modifizierten Compilern, die alle Speicherzugriffe der analysierten Anwendung transparent instrumentieren. Dieser Ansatz hat allerdings zwei Nachteile: Erstens konnen nur Anwendungen untersucht werden, die vom modifizierten Compiler unterstutzt werden, und zweitens muss samtlicher Code der untersuchten Anwendung – inklusive verwendeter Bibliotheken – mit dem modifizierten Compiler ubersetzt werden, da ansonsten Speicherzugriffe aus Anwendungsteilen, die mit einem anderen Compiler ubersetzt wurden, fur den Profiler nicht sichtbar sind. Unser Ansatz verwendet die Performancezahler der GPU anstelle eines modifizierten Compilers. Unser Profiler lagert einzelne Seiten aus dem Grafikspeicher in den Hauptspeicher aus und verwendet anschliesend die Performancezahler, um die Zahl der Hauptspeicherzugriffe der Anwendung zu zahlen. Wird dieser Vorgang einmal fur jede Seite im Adressraum der Anwendung wiederholt, so erhalt man ein vollstandiges Zugriffsprofil des gesamten Speichers in diesem Adressraum. Im Gegensatz zu vorherigen Arbeiten funktioniert dieser Ansatz mit beliebigen Anwendungen und erfasst automatisch samtliche Bibliotheken im Adressraum der Anwendung. Eine Untersuchung von mehreren Anwendungen aus der Rodinia Benchmark Suite mithilfe unseres Profilers zeigt, dass sich die Zahl der Zugriffe pro Seite bei den meisten Anwendungen vor allem zwischen verschiedenen Speicherpuffern der Anwendung unterscheidet, wahrend Seiten innerhalb desselben Puffers meist eine ahnliche Zahl von Zugriffen aufweisen. Ausgehend von den gesammelten Profilen untersuchen wir mehrere mogliche Auslagerungsstrategien und ihre Anwendbarkeit auf aktuellen GPUs. Unser Prototyp enthalt zwei dieser Strategien: Eine wahlt auszulagernde Seiten zufallig aus, wahrend die andere einen prioritatsbasierten Ansatz verwendet. Bei der prioritatsbasierten Strategie weist der Benutzer ausgehend von einem Zugriffsprofil der Anwendung jedem Puffer der Anwendung eine Prioritat zu. Die Auslagerungsstrategie wahlt dann bevorzugt Speicherseiten aus Puffern niedriger Prioritat. Experimente mit beiden Strategien zeigen, dass der prioritatsbasierte Ansatz den Overhead von GPUswap im Vergleich zu zufalliger Auswahl nicht nur deutlich reduziert, sondern sogar in der Lage ist, grosere Datenmengen ohne jeden Overhead auszulagern.