[ Skip to the content ]

Institute of Formal and Applied Linguistics Wiki


[ Back to the navigation ]

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
treex:api-implementation [2016/01/08 14:48]
popel
treex:api-implementation [2016/01/08 19:03]
popel
Line 150: Line 150:
  
 === SORTED-CHILDREN === === SORTED-CHILDREN ===
-Děti se ukládají setříděně buď do pole, nebo do spojáku (tedy každý uzel má pointer _next_node, případně i obousměrně _prev_node). Buď se ukládají pravé a levé děti zvlášť, nebo se při vracení dětí s přepínačem ''add_self'' vloží jejich rodič na správnou pozici. Metoda ''descendants'' uloží potomky do pomocného pole (klasickým průchodem do hloubky) a pak dotřídí. Perl i Python mají sort optimalizovaný na předtříděné sekvence (každý trochu jinak, Perl asi o něco lépe než pythoní timsort, který bere jen sekvence začínající na indexu 2**k, ale pro naše krátké sekvence to je asi úplně jedno). Nejde to implementovat jako iterátor bez toho pomocného pole.+Děti se ukládají setříděně buď do pole, nebo do spojáku (tedy každý uzel má pointer _next_node, případně i obousměrně _prev_node). Buď se ukládají pravé a levé děti zvlášť, nebo se při vracení dětí s přepínačem ''add_self'' vloží jejich rodič na správnou pozici. Metoda ''descendants'' uloží potomky do pomocného pole (klasickým průchodem do hloubky) a pak dotřídí. Perl i Python mají sort optimalizovaný na předtříděné sekvence (každý trochu jinak, Perl asi o něco lépe než pythoní timsort, který bere jen sekvence začínající na indexu 2^k, ale pro naše krátké sekvence to je asi úplně jedno). Nejde to implementovat jako iterátor bez toho pomocného pole.
  
 === SORTED-CHILDREN + ALL-NODES === === SORTED-CHILDREN + ALL-NODES ===
Line 172: Line 172:
  
  
-===== Benchmark načítání CoNLL-U v Perlu ===== +===== Profiling načítání CoNLL-U v Perlu ===== 
-Načítám cs-ud-train-l.conllu (68 MB, 41k sentences, 0.8 MWords) .+Načítám cs-ud-train-l.conllu (68 MB, 41k sentences, 0.8 MWords). Časy v sekundách. Excl(usive) časy se sčítají, krom těch označených "x", což jsou pomocné (alternativní) experimenty.
  
- 0.479s while (<$fh>) {chomp;} +|excl.|incl.| code                                   | note| 
- 0.844s + test $line eq '' or $line =~ /^#/ +0.5 | 0.5 | ''while (<$fh>) {chomp;}''             | načtení řádka po řádce | 
- 1.409s + split /t/, ale hodnoty se zahodí a neukládají do proměnných +0.3 | 0.8 | ''$line eq "" or $line =~ /^#/''       | test prázdné řádky a komentáře | 
- 5.722s totéžale hodnoty atributů se uloží do proměnných (které se hned zahodí) +| 0.7 | 1.5 | ''split /\t/, $line''                  | split 9 atributů dle tabů | 
- 7.724s + uzly se vytvoří jako undefuloží do pole @nodes, které se zahodí, vytváří se bundly +| 4.3 | 5.8 | ''my ($id$form, $lemma,...) =''      | uložení těch hodnot do proměnných | 
- 3.500s vytvoření pole s 0.8M uzlů se všemi atributy (žádné čtení souboru, všechny uzly stejné) +|x3.9 |     | ''UD::Node->new(form=>$form,...)''     vytvoření 0.8M uzlů se stejnými atributy| 
- 7.887s totéžale atributy se vytvářejí splitem jedné řádky +| 4.5 |10.3 | ''UD::Node->new(form=>$form,...)''     | vytvoření 0.8M uzlů ze skutečných dat| 
-12.552s vytváří se uzly ze souboruale nedávají se do stromů, jen do pole, toto by mělo odpovídat 5.722s+3.500s +|x0.4 |10.7 | ''push @all_nodes$node''             | uzly se ukládají do pole
-10.917s nedělá se split ani rehang, všechny atributy jsou prázdný řetězecstromy ale mají uzly +| 1.9 |12.2 | ''weaken($node->{_parent}=$root)...''  | uzly se ukládají do dokumentu, věší se na kořenpřidávají do jeho seznamu dětí| 
-13.460s korektní načtení, netestují se cykly, nevolá se set_parent (ale zopakuje se jeho kód+| 1.2 |13.4 | ''weaken($node->{_parent}=$parent)...''| uzly se věší na skutečného rodiče (v druhém průchodu, pomocné pole ''@parents'')| 
-15.903s korektní načtení, netestují se cykly, volá se set_parent($parent, {cycles=>'no-check'}) +| 2.5 |15.9 | ''set_parent($parent,{cycles=>'no-check'})'' | set_parent místo optimalizovaného kódu (který neřešil předchozího rodiče atd.)| 
-16.646s korektní načtení, testují se cykly, volá se set_parent($parent) +| 0.7 |**16.6**| ''set_parent($parent)''                | testování cyklů | 
-26.666s původní implementace načítání, kde se uzly vytvářejí pomocí $root->create_child a převěšují se pak z kořene na skutečného rodiče a děti jsou pole +|10.0 |26.6 | ''$root->create_child...''             původní implementace, kde se uzly převěšují z kořene na skutečného rodiče a děti jsou pole|
-19.029s totéž, ale bez převěšování, tedy vše visí na kořenu+
  
  
-  * Původní implementace byla velmi neefektivní, protože se při převěšování z kořene musely uzly odebrat z pole dětí kořene, čili se muselo to pole překopírovat a zmenšit o jeden prvek a složitost byla kvadratická. Převěšení trvalo 7s. Kdyby byly děti implementované spojákem místo pole (to mám stále v plánu), tak to bude rychlejší, ale stejně je zbytečné při načítání CoNLL-U uzly dávat do spojáků dětí kořene, ze kterého vím, že je budu za chvíli odebírat. +  * Původní implementace byla velmi neefektivní, protože se při převěšování z kořene musely uzly odebrat z pole dětí kořene, čili se muselo to pole překopírovat a zmenšit o jeden prvek a složitost byla kvadratická. Samotné převěšení trvalo 7s (a ještě 3s asi kvůli ''$root->create_child(...)'' místo ''UD::Node->new(...)''). Kdyby byly děti implementované spojákem místo pole (to mám stále v plánu), tak to bude míň než 7s, ale stejně je zbytečné při načítání CoNLL-U uzly dávat do spojáků dětí kořene, ze kterého vím, že je budu za chvíli odebírat. 
-  * Ušetřil jsem 10stedy víc než 7sVolám přímo ''UD::Node->new(...)'' místo ''$root->create_child(...)''+  * Vypuštěním testování cyklů v CoNLL-závislostech se ušetří necelá sekundacož za to asi nestojí 
-  * Ještě víc by šlo ušetřit vypuštěním testování cyklů v CoNLL-U závislostech (1s) optimalizací kódu set_parent bez volání této metody (další 2s). +  * Optimalizací kódu set_parent bez volání této metody se jakoby ušetří 2.5s. 
-  * Nyní se nejvíc času stráví samotným vytvářením uzlů (10.917s-0.844s). To musím ještě prozkoumat.+  * Poměrně dost času (4.3s) zabere vytváření 9 proměnných ''$form, $lemma,...''. Nešikovné je, že při ''UD::Node->new(form=>$form,...)'' se tyto proměnné zkopírují do hashe a ty původní vypadnou ze scope musejí se odalokovat. Čili vytváření uzlu zabere skoro stejný čas (4.5s). 
 +  * Když jsem všechny uzly ukládal do pole, tak odalokování pole (0.8M uzlůtrvalo cca 1s. To jsem do profilingu nezahrnul, ale benchmark jsem musel ručně spouštět víckrát.
  
 ===== Benchmark konstruktorů v Perlu ===== ===== Benchmark konstruktorů v Perlu =====

[ Back to the navigation ] [ Back to the content ]