Pro­gram­ma's star­ten met Py­thon ipv Bash

Met Py­thon- in plaats van Bash-scripts pro­gram­ma's star­ten en re­sul­ta­ten ver­wer­ken

C’t Magazine - - Inbound 6/2018 - Pi­na Mer­kert

Van­uit Py­thon kun je ook zon­der al te­veel moei­te pro­gram­ma's star­ten die in an­de­re ta­len ge­schre­ven zijn. Py­thon-pro­gram­ma's heb­ben voor ty­pi­sche pro­gram­meer­ta­ken ech­ter we­zen­lijk min­der co­de no­dig dan Bash-scripts. Daar­om is Py­thon met zijn ele­gan­te­re co­de pri­ma ge­schikt om Bash te ver­van­gen.

Voor het tes­ten van een nieu­we gra­fi­sche kaart ge­brui­ken we on­der meer de ma­chi­ne-learning­ben­ch­mark DeepBench. Die in C ge­pro­gram­meer­de ben­ch­mark be­staat uit drie af­zon­der­lij­ke tests die elk twee pa­ra­me­ters ac­cep­te­ren en een he­le bat­te­rij aan tijd­me­tin­gen op­le­ve­ren, bij­voor­beeld voor ma­trix­ver­me­nig­vul­di­gin­gen met ma­tri­ces van ver­schil­len­de grootte. Om on­zui­ve­re re­sul­ta­ten door er toe­val­lig tus­sen­door glip­pen­de sys­teem­pro­ces­sen te ver­mij­den, voe­ren we el­ke ben­ch­mark drie keer uit en ge­brui­ken we daar tel­kens het bes­te re­sul­taat van. Van die re­sul­ta­ten be­re­ke­nen we het meet­kun­dig ge­mid­del­de om tot één en­ke­le waar­de per test te ko­men. Dat le­vert een to­taal­re­sul­taat voor de per­for­man­ce van een gra­fi­sche kaart bij dit ty­pe be­re­ke­nin­gen. Je kunt de be­no­dig­de 45 tests hand­ma­tig star­ten, de re­sul­ta­ten in Ex­cel zet­ten en daar het re­sul­taat mee be­re­ke­nen, maar de test­com­pu­ter kan dat au­to­ma­tisch he­le­maal zelf doen met een Py­thon-script. Dit voor­beeld laat zien hoe mak­ke­lijk Py­thon Bash-scripts en Bash­be­stan­den kan ver­van­gen.

Een Bash-script zou de 45 af­zon­der­lij­ke tests met een paar loops re­la­tief mak­ke­lijk kun­nen star­ten. Bij het ver­wer­ken van de re­sul­ta­ten moet je dan wel wat ma­gi­sche sed-com­man­do's be­den­ken om uit de con­so­le-uit­voer van de ben­ch­marks de juis­te ge­tal­len er­uit te pik­ken. Bij het be­re­ke­nen van het meet­kun­dig ge­mid­del­de zou je dan wil­len dat je een bi­bli­o­theek als NumPy zou heb­ben, maar die is er voor Bash niet in zo'n han­di­ge vorm.

Py­thon kan de scripts met net zo wei­nig co­de uit­voe­ren als een Bash-script, maar dan met be­hulp van re­gu­lie­re ex­pres­sies ook de re­sul­ta­ten er re­la­tief mak­ke­lijk uit ex­tra­he­ren. Dat is mo­ge­lijk door de mo­du­les sub­pro­cess, re en numpy. De eerste kan wil­le­keu­ri­ge pro­gram­ma's als ei­gen pro­ces star­ten. De an­de­re ex­tra­he­ren en ver­wer­ken de da­ta.

Met sub­pro­cess.Po­pen() start je pro­gram­ma's van­uit Py­thon die je ook via de con­so­le kunt star­ten. Het com­man­do ver­wacht als pa­ra­me­ter een lijst met als eerste item de naam van het pro­gram­ma en daar­na de daar­voor be­no­dig­de pa­ra­me­ters. Het star­ten van ../DeepBench/co­de/bin/ con­v_­bench train flo­at wordt dan prc = sub­pro­cess.Po­pen([ "../DeepBench/co­de/bin/con­v_­bench", "train", "flo­at"])

Als je Po­pen() dan nog de pa­ra­me­ter st­dout=sub­pro­cess.PIPE mee­geeft, stuurt het pro­gram­ma zijn uit­voer door via een pipe. Die kun je met com­mu­ni­ca­te() be­na­de­ren:

out = prc.com­mu­ni­ca­te()[0]

In out staat dan al­le uit­voer die het ge­star­te pro­gram­ma nor­maal ge­spro­ken naar de con­so­le ge­schre­ven zou heb­ben.

Re­sul­ta­ten ver­wer­ken

DeepBench voert de re­sul­ta­ten uit als een soort ta­bel die ge­for­mat­teerd is met spa­ties. Dat is een for­maat dat in prin­ci­pe niet han­dig is om ver­der te ver­wer­ken, maar de uit­voer ziet er in elk ge­val al­tijd het­zelf­de uit. Daar­om kun je de re­sul­ta­ten fil­te­ren met re­gu­lie­re ex­pres­sies. De Py­thon-mo­du­le re

doet dat. On­ze re­gu­lie­re ex­pres­sie ver­wacht ge­he­le ge­tal­len \d+ die ge­schei­den zijn door min­stens één spa­tie \s+. Om­dat we de ge­tal­len ver­der wil­len be­wer­ken, ma­ken we een cap­tu­ring-group aan door de ge­tal­len tus­sen ron­de haak­jes te zet­ten (\d+). Met re.com­pi­le() maak je van de string een re­gu­lie­re-ex­pres­sie-ob­ject. Als je daar de me­tho­de match() mee uit­voert, en je er tel­kens één re­gel van de ben­ch­mark-uit­voer aan mee­geeft, ont­staat hier­bij een Match-ob­ject. Aan de door de re­gu­lie­re ex­pres­sie ge­de­fi­ni­eer­de groe­pen (de de­len van het com­man­do die tus­sen ron­de haak­jes staan) kun je ko­men met be­hulp van match.groups(). In een iets kor­te­re vorm ziet de co­de daar­voor er als volgt uit:

res_­li­ne = re.com­pi­le(r"^\s*(\d+)\s+

d+)\s+(\w+)\s*$") for li­ne in out.split­lines(): match = res_­li­ne.match(li­ne) if match: p, fw_­ti­me, f_alg =

match.groups()

Ma­trix­re­ke­nen

De daar­na met be­hulp van re ge­ëx­tra­heer­de ben­ch­mar­kre­sul­ta­ten wor­den sim­pel­weg naar de lijst re­sults ge­schre­ven. Elk item op de lijst be­staat op zijn beurt uit een lijst van drie waar­den, na­me­lijk het re­sul­taat van de af­zon­der­lij­ke ben­ch­mark­tests. Van die lijst van lijs­ten maakt np.ar­ray(re­sults) een ma­trix. Daar kan NumPy ver­vol­gens mak­ke­lijk mee re­ke­nen. Met min(axis=0) zoek je bij­voor­beeld naar de klein­ste waar­de in el­ke ko­lom, zo­dat daar een vec­tor bij ont­staat:

np.ar­ray(re­sults).min(axis=0)

Daar­na staan in die vec­tor de tij­den van de bes­te uit drie ben­ch­mar­kruns voor el­ke af­zon­der­lij­ke test.

Maar we wil­len lie­ver een en­ke­le waar­de als re­sul­taat ge­ven in plaats van een he­le vec­tor. Die waar­de wordt dan be­re­kend als het meet­kun­dig ge­mid­del­de van de re­sul­ta­ten van de af­zon­der­lij­ke tests, res­pec­tie­ve­lijk de co­ör­di­na­ten van de vec­tor. Een func­tie voor het be­re­ke­nen van het meet­kun­dig ge­mid­del­de zit in de mo­du­le sci­py. stats on­der de naam gmean. Sci­Py komt van de­zelf­de ont­wik­ke­laars als NumPy en be­vat hon­der­den func­ties voor we­ten­schap­pe­lij­ke be­re­ke­nin­gen. Het be­re­ke­nen van het to­taal­re­sul­taat past daar­door op één re­gel:

gmean(np.ar­ray(re­sults).min(axis=0))

Niets meer met de hand

De voor­de­len van Py­thon ten op­zich­te van Bash zijn dan ook het grootst als je niet al­leen pro­gram­ma's start met sub­pro­cess.Po­pen(), maar bo­ven­dien de re­sul­ta­ten er­van ver­der wilt be­wer­ken. De be­re­ke­nin­gen kun je in Py­thon met een stuk min­der re­gels de­fi­ni­ë­ren dan in de con­so­le.

Het com­ple­te voor­beeld voor het ana­ly­se­ren met DeepBench staat bij de link hie­ron­der. Daar staan extra co­de­re­gels in om de ver­schil­lend ge­for­mat­teer­de uit­voer van de af­zon­der­lij­ke tests tel­kens op de juis­te ma­nier te ex­tra­he­ren. Al­le uit­gangs­pun­ten ach­ter de scripts heb je ech­ter in dit ar­ti­kel kun­nen le­zen. (nkr)

DeepBench laat de tal­rij­ke tijd­me­tin­gen zien als een op­ge­maak­te ta­bel. Het Py­thon-script ver­werkt die da­ta vol­le­dig au­to­ma­tisch.

Newspapers in Dutch

Newspapers from Netherlands

© PressReader. All rights reserved.