|
|
Erste Performancemessungen von OMA
Erste Performancemessung von OMATorsten Will
Zusammenfassung
Es wurde eine spezielle Version von OMA implementiert,
die fuer einen Vergleich mit MSA gedacht ist. Das Programm
heisst testMsa/1 und hat gegenueber MSA den
algorithmischen Zusatz, GDUS (Goal Directed Unidirectional
Search, A*-Algorithmus) implementiert zu haben.
Eine Performancemessung wurde fuer mehrere
Testdatensaetze durchgefuehrt.
|
(Zurück)
|
EinleitungtestMsa/1 versucht das Verhalten von Msa
2.1 auf folgende Weise nachzuahmen:
- MSA wird mit -g und -b aufgerufen: "gleiche Gewichtung" und
"TermGaps zaehlen". Das heuristische Alignment von MSA liefert
die obere Schranke fuer die OMA Algorithmen.
- GDUS ist eingeschaltet, SmartPrio wird
verwendet
- Eine Segmentierung oder Iteration ueber die Segmentlaengen
findet nicht statt
Sowohl bei MSA 2.1, als auch bei testMsa/1 sind allerlei
Zaehlungen und Messungen eingefuegt worden um die Performance
messen zu koennen.
Sequenzdaten
Alle Tests wurden mit der Kostenmatrix dayhoff.cost
durchgefuehrt.
Die verwendeten Sequenzdaten haben folgende Merkmale:
- prot5.seq, prot6.seq und prot7.seq: 5, 6 und 7
Protein-Sequenzen mit Laengen um etwa 70
- diplom.2.fasta: Gleichnamiger Datensatz aus [GSA2], meiner
Dipl.; 5 Sequenzen mit Laengen um etwa 120
- diplom.8.fasta: (oder auch diplom.4.fasta) [GSA2]; 8
Sequenzen mit Laengen ab 420-460
- diplom.9.fasta: (oder auch diplom.5.fasta) [GSA2]; 9
Sequenzen mit Laengen ab 420-460
Testreihe 1
- cost: Kosten des berechnet Alignments. "=" heisst
das das Programm den gleichen Wert lieferte.
- Objects: Anzahl der konstruierten (OMA-Library)
Objekte insgesamt
- Edge: Anzahl der konstruierten Edge-Objekte
- reins E: Durch die Verwendung von GDUS mehrfach in
die Queue eingefuegte Edges.
- Vertex: Anzahl der konstruierten Vertex-Objekte
- face invalid: Anzahl der mindestens einmal besuchten
Gitterpunkte, die ausserhalb des face gueltigen Bereichs liegen
und fuer die daher kein Vertex kreiert wurde.
- time real/user: mit time angezeigte Zeit in [s]
- mem[8kb]: Maximal angeforderter Speicher in
8kb-Pages
-
htX: Performancemessungen bei den Hashtables, die an
zwei Stellen im Programm verwendet werden; Q steht fuer die
PriorityQueue und T fuer den Trie
- gets/puts: Anzahl der get/put-Operationen. Die
angegebenen Werte sind ohne die benoetigten Operationen
waehrend Rehashings angegeben.
- probes: Es wird open adressing verwendet. Das
Verhaeltnis von "probes" zu "gets+puts" ist ein Mass fuer
die Performance.
Der verwendete Hashfunktion ist /1.0 aus Tabelle 2.
| |
prot5 |
prot6 |
prot7 |
diplom.2 |
| msa lower |
10 712 |
16 074 |
22 501 |
18 374 |
| msa delta |
54 |
147 |
250 |
315 |
| oma delta |
54 |
156 |
303 |
329 |
| cost |
10 766 |
16 221 |
22 751 |
18 689 |
| Objects |
5 155 |
20 002 |
72 796 |
737 288 |
| Edge |
390 |
7 796 |
31 555 |
679 566 |
| reins E |
12 |
31 |
59 |
1 844 |
| Vertex |
338 |
1 289 |
2 832 |
40 924 |
| face invalid |
3 940 |
19 971 |
78 469 |
85 599 |
| time real |
5.4 |
24.2 |
4m37.0 |
29m14.2 |
| time user |
4.5 |
23.3 |
4m36.2 |
29m12.0 |
| mem[8kb] |
1 339 |
1 592 |
2 183 |
7 746 |
| htQ gets |
565 |
38 463 |
269 060 |
12 319 572 |
| htQ puts |
390 |
7 796 |
31 555 |
679 566 |
| htQ probes |
955 |
47 004 |
316 940 |
21 144 799 |
| htQ perf |
1.00 |
1.02 |
1.05 |
1.62 |
| htT gets |
77 894 |
2 077 167 |
22 613 261 |
88 015 867 |
| htT puts |
7 017 |
29 724 |
116 306 |
140 825 |
| htT probes |
117 323 |
4 620 620 |
156 626 061 |
213 402 635 |
| htT perf |
1.38 |
2.19 |
6.89 |
2.42 |
Tabelle 1:
Performance mit verschiedenen Sequenzdaten und
h2/1.0 |
|
Hashtable-PerformanceDie Messergebnisse fuer die Hashtabelle
bescheinigen eine schlechte Performance fuer die
Trie-Implementierung. Die Eigenschaft der Trie-Implementierung
ist, dass zu einem TrieBranch fuer jeden ChildNode ein Schluessel
aus dem Paar (k1,k2) verwendet wird, mit
- k1 = "Speicheradresse dieses TrieBranch" und
- k2 = "Ordinate dieses ChildNodes in dieser
Triedimension"
Es werden also fuer k2 nur Werte aus [0..n] verwendet (mit n
= Sequenzlaengen). Das wirkt sich negativ auf das Clustering in
der Hashtabelle aus. Dass sich schlechte Performance vor allem
bei prot7 zeigt, ist ein weiteres Indiz fuer diesen Grund. Jeder
einzelne Wert aus dem Intervall [0..n] kommt mit einer
Haeufigkeit von O(|V|) vor. Da |V|=n^k steigt die Haeufigkeit
jedes k2 exponentiell zur Sequenzanzahl Das Beispiel prot7 wurde
mit mehreren Varianten von types/Hashtable2dim.cpp
durchgerechnet. Die folgenden Hashvarianten fuer Hashfunktion 2
(h2) wurden verwendet:
- /1.0:
h2 = (k2<<4)^(k2<<1) | 1;
Wurde auch fuer die Messungen von Tbl.1 verwendet.
- /1.1:
h2 = k1 ^ k2; h2 = (h2<<4) ^
(h2<<1) | 1;
| Version |
htT probes |
htT perf |
| /1.0 |
156 626 061 |
6.89 |
| /1.1 |
30 691 786 |
1.35 |
| Tabelle 2:
Verschiedene h2() |
|
Schon der erste Verbesserungsversuch zeigte Erfolg.
Eigentlich sollten die Hashfunktionen voneinander unabhaenig
sein. Doch liess sich die Haeufung auf h2 an dieser zentralen
Stelle am leichtesten beheben. Zudem wird h1 auf voellig andere
Weise berechnet, so dass h1 und h2 noch ausreichend
unterschiedlich sind:
union union_long_double {
long longvalue;
double doublevalue;
};
union_long_double ld;
ld.doublevalue = (((double)k1)+PI) * hashA1; // hashA1 is a "good" float number
h1 = ld.longvalue;
Mit 1.35 probes pro Tabellenzugriff liegt das Ergebnis auch
im theoretisch guten Bereich [Cormen 90, "Intro to Algo"], [Knuth
73, "TAOCP-3"], [Sedgewick92]. Es sei noch angemerkt, dass diplom.2
mit 118.259.625 probes seine Performance nahezu verdoppelte. Trotz
der 100 Millionen weniger probes ging die verbrauchte Zeit dabei
nur um etwa 1m auf 28m5.5s zurueck.
Testreihe 2Der
verwendete Hashfunktion ist /1.1 aus Tabelle 2.
|
diplom.8 |
diplom.9 |
| msa lower |
171 547 |
220 922 |
| msa delta |
283 |
354 |
| cost |
171 830 |
221 276 |
| Objects |
1 303 407 |
1 385 651 |
| Edge |
926 907 |
565 378 |
| reins E |
155 |
200 |
| Vertex |
50 592 |
47 897 |
| face invalid |
448 715 |
975 567 |
| time real |
23m27.1 |
33m43.2 |
| time user |
23m15.1 |
33m29.5 |
| mem[8kb] |
56 613 |
65 648 |
| htQ gets |
2 532 644 |
1 359 582 |
| htQ puts |
926 907 |
565 378 |
| htQ probes |
8 602 899 |
4 567 433 |
| htQ perf |
2.49 |
2.37 |
| htT gets |
81 165 423 |
160 767 463 |
| htT puts |
800 410 |
1 763 856 |
| htT probes |
140 053 420 |
290 449 756 |
| htT perf |
1.71 |
1.78 |
Tabelle
3:
Performance mit weiteren
Sequenzdaten und h2/1.1 |
|
Es wurde eine "Final Release" des Programms testMsa erstellt,
d.h. alle zeitkritischen Debug-Ausgaben und -Messungen wurden
entfernt. Daher koennen nur noch Zeit- und Speichermasse fuer die
Performance angegeben werden. Es wurde mit Optimierung (mit dem
SunPro-Compiler) compiliert.
Einige kleinere Aenderungen duerften die Performance noch
leicht verbessert haben.
Ausserdem wurde der Speicherverbrauch an einer wichtigen
Stelle noch gezielt auf die Tests optimiert: Grosse Teile der
Distanzmatrizen werden vor den Start des Hauptalgorithmus
entfernt.
Der verwendete Hashfunktion ist h2/1.1 aus Tabelle
2.
Der verwendete Rechner fuer die Messungen war q.
Diese Programmversion nennen wir testMsa/2.1/final.
|
prot5 |
prot6 |
prot7 |
dipl.2 |
dipl.8 |
dipl.9 |
| cost |
10 766 |
16 221 |
22 751 |
18 693 |
171 830 |
221 276 |
| time user |
0.6 |
3.0 |
27.8 |
278.6 |
241.7 |
371.3 |
| mem[8kb] |
891 |
982 |
1 295 |
6 631 |
26 986 |
31 528 |
Tabelle 3:
Zeit und Speicher von testMsa/2.1/final |
|
Protokoll ErlaeuterungHier ein Beispiel fuer die Ausgabe
am Ende eines Durchlaufs von testMsa/1 und dazu einige
Erlaeuterungen.
[ 1] EQVertexmap: gets:1359582, puts:565378, probes:4567433, rehashes:2
[ 2] Counted reinserted edges: 200
[ 3] Visited different face invalid Vertex's (hull of search space): 975567
[ 4] TrieChildmap: gets:160767463, puts:1763856, probes:290449756, rehashes:5
[ 5]
[ 6] gsa2-cost: 221276
[ 7] Object:+1385652-1385651=1
[ 8] Exception:+0-0=0
[ 9] Edge:+565378-565378=0
[10] Vertex:+47897-47897=0
[11] #MemAfter:
[12] F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
[13] 8 S 1613 8016 7973 9 99 20 7ad064f8 65648 7ad06568 pts/14 33:35 testMsa
[14]
[15] real 33m43.220s
[16] user 33m29.500s
[17] sys 0m12.150s
- [1] Performance der Hashtable der EdgeQueue. Sie dient zum
Auffinden eines Edges anhand seiner beiden Endpunkt-Vertices.
Angegeben ist die Zahl der Basisoperationen des Hashtables
ausserhalb von Rehashings.
- [2] Bei GDUS werden Kanten auch nach dem Ausfuegen aus der
Queue wieder eingefuegt. Hier die Anzahl dieser Faelle.
- [3] Bei der Aufzaehlung der Nachbarn eines Vertextes wird
jeder Nachbar geprueft, ob er face gueltig ist. Hier ist die
Anzahl der besuchten Vertices, die nicht face gueltig waren.
Fuer jeden dieser ungueltigen Vertices wird ein Element in den
Trie eingetragen (siehe htT).
- [4] Performance der Hashtabelle des Tries, mit dem die
Koordinaten der Vertices verwaltet werden. Die Tabelle
implementiert die Beziehung: "Adresse des Kindknotens" =
get("Adresse Vaterknoten", "Ordinate Kindknoten").
- [6] Kosten des berechneten Alignments.
- [7] Gezaehlte OMA-Objekte: "+" aufgerufene Konstruktoren,
"-" Destruktoren, "=" MemLeaks und statische Objekte.
- [8] Gezaehlte OMA-Exceptions.
- [9] Gezaehlte Edge-Objekte.
- [10] Gezaehlte Vertex-Objekte.
- [11-13] Ausgabe von "ps" zum Programmaufruf, kurz vor Ende.
Unter SZ steht die Anzahl der angeforderten Speicherzeiten,
hier zu je 8kb Groesse.
- [15-17] Ausgabe von "time" zum Programmaufruf.
|
|