Omdat ik sinds kort een Core2 Duo heb, ben ik eens aan het optimaliseren gegaan voor multicore in 1 van m'n hobby-projecten.
Ik heb gekozen voor 1 van de zwaarste CPU-routines die ik gemaakt heb, namelijk het 3d vuur-effect, met het MarchingCubes-algoritme.
Mijn eerste poging was om het algo precies hetzelfde te laten werken als voor single-core, zodat het een optimale vertexbuffer voor de videokaart op zou leveren.
Dat had als nadeel dat de threads iets meer geheugen moesten delen.
Op de Core2 Duo zag het er goed uit, ruim 30% sneller dan de single-core versie.
Maar toen ik het op een Athlon X2 ging draaien, werd het niet sneller.
Op een Pentium D werd het zelfs iets langzamer.
Back to the drawing board dus... Een alternatief idee dat ik had was om iedere thread z'n eigen vertexbuffer te laten genereren. Dat betekende wel wat meer werk voor de GPU, maar als het de CPUs sneller kan laten werken, heft dat elkaar misschien toch weer op.
Hoewel ik het niet verwachtte, bleek dit op m'n Core2 Duo toch nog een fractie sneller te zijn, nu rond de 37-38%. Ik denk dat het hem hier vooral zit in het feit dat ik wat kopieer-operaties uitspaar, doordat ik de vertices niet meer hoef samen te voegen in 1 buffer.
En de magie begon nu ook te gebeuren op de Athlon X2 en de Pentium D.
Op een X2 4400+ ging het er zo'n 40% op vooruit.
Een Pentium D 805 ging zelfs met 47% vooruit.
Toen heb ik ook nog even een Pentium 4 HT erbij gehaald... en dat was ook interessant. Het nieuwe algoritme zorgde daar ook nog voor een paar procentjes winst. Maar vooral opvallend was dat daar de oude multithreaded versie niet trager werd. Je zou verwachten dat als twee echte cores het er lastig mee hebben, dat een enkele core met HT het nog drukker krijgt.
Wat de Pentium 4 gemeen heeft met de Core2 Duo is dat ze beiden een enkele L2-cache hebben, die voor beide threads gebruikt wordt.
Ik denk dat dat het grote voordeel is ten opzichte van de Pentium D en Athlon X2.
Eerst dacht ik dat het misschien ook met de bandbreedte te maken had... dat de singlethreaded versie al zo hongerig was dat er voor een tweede thread geen bandbreedte meer over was om nog sneller te gaan. Maar aangezien de Pentium HT niet langzamer is, lijkt me dat niet het geval... hij gebruikt inderdaad meer bandbreedte, omdat hij aan het eind de vertexbuffers samenvoegt... In principe is het multithreaded deel van het algoritme dan wel sneller, omdat dit extra werk 'gratis' is. Dus die extra bandbreedte is er.
Mijn conclusie is dus dat shared L2-cache erg belangrijk is voor efficient multithreaden. De Athlon X2 en Pentium D hebben dit niet... en hoewel de Athlon X2 op papier efficienter is dan de Pentium D, is het in de praktijk niet zo heel relevant (in dit geval tenminste). Op de Athlon is het nog dermate inefficient dat de single-threaded versie ongeveer even snel is (maar wel met 50% minder CPU-gebruik).
In dit geval kon ik eromheen programmeren, maar dat zal niet altijd kunnen. In die gevallen is de Core2 Duo dan oppermachtig, vanwege de shared L2-cache.
Dus, is de Athlon X2 een beter dualcore-ontwerp dan de Pentium D? Ja.
Is het een goed dualcore-ontwerp? Nee, het is marginaal beter dan de Pentium D in worst case, maar nog steeds niet geweldig... Er zit nog steeds een gat van 40% tussen worst case en best case. De Core2 Duo is in die worst case maar een marginaal langzamer dan in de best case, misschien 5% hooguit.
Dat betekent dus dat de Core2 veel meer mogelijkheden opent tot het optimaliseren van algoritmen voor multithreading.
Hoe ziet de nabije toekomst eruit?
De Kentsfield van Intel is een soort combinatie van Core2 Duo en Pentium D. Per 2 cores heb je dus al die shared L2-cache die in sommige gevallen een groot verschil maakt. De andere cores communiceren dan nog wel via de FSB, maar die sneller dan bij de Pentium D (die al bijna net zo goed werkte als de K8), en is minder vaak nodig.
De K8L heeft geen shared L2-cache, maar L3-cache. Dit zal het probleem van de K8 iets verlichten, maar het zal een stuk langzamer zijn dan shared L2-cache, dus ik denk dat hij het in veel gevallen tegen de Kentsfield moet gaan afleggen bij dit soort algoritmen (zeker omdat ik ook niet verwacht dat de K8L per core sneller zal zijn, omdat de Core2 een indrukwekkende IPC heeft, en ook aardig ver kan schalen qua kloksnelheid).
Tot slot nog even de drie binaries waarmee ik getest heb:
http://scali.eu.org/~bohemiq/Fire.rar
De multithread-versies gebruiken OpenMP... hiervoor moet je de VC++ redist installeren, als je die nog niet hebt:
http://go.microsoft.com/fwlink/?linkid=65127&clcid=0x409
Als iemand een systeem met meer dan 2 cores heeft, lijkt het me wel interessant om een versie te maken die daar gebruik van maakt, om te kijken hoever dit algoritme nu kan schalen (de huidige versie gebruikt maar twee threads, dus zal op een quadcore oid niet sneller zijn).
Ik heb gekozen voor 1 van de zwaarste CPU-routines die ik gemaakt heb, namelijk het 3d vuur-effect, met het MarchingCubes-algoritme.
Mijn eerste poging was om het algo precies hetzelfde te laten werken als voor single-core, zodat het een optimale vertexbuffer voor de videokaart op zou leveren.
Dat had als nadeel dat de threads iets meer geheugen moesten delen.
Op de Core2 Duo zag het er goed uit, ruim 30% sneller dan de single-core versie.
Maar toen ik het op een Athlon X2 ging draaien, werd het niet sneller.
Op een Pentium D werd het zelfs iets langzamer.
Back to the drawing board dus... Een alternatief idee dat ik had was om iedere thread z'n eigen vertexbuffer te laten genereren. Dat betekende wel wat meer werk voor de GPU, maar als het de CPUs sneller kan laten werken, heft dat elkaar misschien toch weer op.
Hoewel ik het niet verwachtte, bleek dit op m'n Core2 Duo toch nog een fractie sneller te zijn, nu rond de 37-38%. Ik denk dat het hem hier vooral zit in het feit dat ik wat kopieer-operaties uitspaar, doordat ik de vertices niet meer hoef samen te voegen in 1 buffer.
En de magie begon nu ook te gebeuren op de Athlon X2 en de Pentium D.
Op een X2 4400+ ging het er zo'n 40% op vooruit.
Een Pentium D 805 ging zelfs met 47% vooruit.
Toen heb ik ook nog even een Pentium 4 HT erbij gehaald... en dat was ook interessant. Het nieuwe algoritme zorgde daar ook nog voor een paar procentjes winst. Maar vooral opvallend was dat daar de oude multithreaded versie niet trager werd. Je zou verwachten dat als twee echte cores het er lastig mee hebben, dat een enkele core met HT het nog drukker krijgt.
Wat de Pentium 4 gemeen heeft met de Core2 Duo is dat ze beiden een enkele L2-cache hebben, die voor beide threads gebruikt wordt.
Ik denk dat dat het grote voordeel is ten opzichte van de Pentium D en Athlon X2.
Eerst dacht ik dat het misschien ook met de bandbreedte te maken had... dat de singlethreaded versie al zo hongerig was dat er voor een tweede thread geen bandbreedte meer over was om nog sneller te gaan. Maar aangezien de Pentium HT niet langzamer is, lijkt me dat niet het geval... hij gebruikt inderdaad meer bandbreedte, omdat hij aan het eind de vertexbuffers samenvoegt... In principe is het multithreaded deel van het algoritme dan wel sneller, omdat dit extra werk 'gratis' is. Dus die extra bandbreedte is er.
Mijn conclusie is dus dat shared L2-cache erg belangrijk is voor efficient multithreaden. De Athlon X2 en Pentium D hebben dit niet... en hoewel de Athlon X2 op papier efficienter is dan de Pentium D, is het in de praktijk niet zo heel relevant (in dit geval tenminste). Op de Athlon is het nog dermate inefficient dat de single-threaded versie ongeveer even snel is (maar wel met 50% minder CPU-gebruik).
In dit geval kon ik eromheen programmeren, maar dat zal niet altijd kunnen. In die gevallen is de Core2 Duo dan oppermachtig, vanwege de shared L2-cache.
Dus, is de Athlon X2 een beter dualcore-ontwerp dan de Pentium D? Ja.
Is het een goed dualcore-ontwerp? Nee, het is marginaal beter dan de Pentium D in worst case, maar nog steeds niet geweldig... Er zit nog steeds een gat van 40% tussen worst case en best case. De Core2 Duo is in die worst case maar een marginaal langzamer dan in de best case, misschien 5% hooguit.
Dat betekent dus dat de Core2 veel meer mogelijkheden opent tot het optimaliseren van algoritmen voor multithreading.
Hoe ziet de nabije toekomst eruit?
De Kentsfield van Intel is een soort combinatie van Core2 Duo en Pentium D. Per 2 cores heb je dus al die shared L2-cache die in sommige gevallen een groot verschil maakt. De andere cores communiceren dan nog wel via de FSB, maar die sneller dan bij de Pentium D (die al bijna net zo goed werkte als de K8), en is minder vaak nodig.
De K8L heeft geen shared L2-cache, maar L3-cache. Dit zal het probleem van de K8 iets verlichten, maar het zal een stuk langzamer zijn dan shared L2-cache, dus ik denk dat hij het in veel gevallen tegen de Kentsfield moet gaan afleggen bij dit soort algoritmen (zeker omdat ik ook niet verwacht dat de K8L per core sneller zal zijn, omdat de Core2 een indrukwekkende IPC heeft, en ook aardig ver kan schalen qua kloksnelheid).
Tot slot nog even de drie binaries waarmee ik getest heb:
http://scali.eu.org/~bohemiq/Fire.rar
De multithread-versies gebruiken OpenMP... hiervoor moet je de VC++ redist installeren, als je die nog niet hebt:
http://go.microsoft.com/fwlink/?linkid=65127&clcid=0x409
Als iemand een systeem met meer dan 2 cores heeft, lijkt het me wel interessant om een versie te maken die daar gebruik van maakt, om te kijken hoever dit algoritme nu kan schalen (de huidige versie gebruikt maar twee threads, dus zal op een quadcore oid niet sneller zijn).