# MT

## Přehled

autor: tsp
verze: 0.7
stáhnout: http://www.avisynth.org/tsp/, http://www.avisynth.org/warpenterprises/
kategorie: Různé pluginy
požadavky:

licence: GPL

## Obsah

- MT 0.7

- Úvod
- Technické info
- Syntaxe

- MT
- MTi
- MTsource

- Příklady
- Seznam změn

- Modifikovaný avisynth 2.5.7.5

- Úvod
- Příklad:
- Jak vyvíjet vláknově bezpečné filtry

- Odkazy

## MT 0.7

`MT`(clip clip,string filter,int threads,int overlap,bool splitvertical)

`MTi`(clip clip,string filter)

`MTsource`(string filter,int delta,int threads)

### Úvod

MT je filtr, který umožňuje jiným filtrům běžet na více vláknech. To by mělo urychlit zpracování na hyperthreaded/vícejádrových procesorech nebo víceprocesorových systémech.

Důležité: Nikdy nezapomeňte posoudit výsledek pohledem na zvýšení rychlosti a ne jen využití cpu.

Také se podívejte na MT support page pro více informací než požádáte o pomoc

### Technické info

MT je filtr, který rozděluje snímek na malé fragmenty, které jsou zpracovány v jednotlivých vláknech a tím umožní plné využití víceprocesorových nebo hyperřetězených (hyperthread) počítačů. Testoval jsem ho na mém starém abit bp6 s 2x celeron 400 MHz a zvýšil rychlost o 40%. Všimněte si, že pokud už máte 100% zatížení cpu při zpracování avs skriptů bez MT (t.j pokud enkódujete do DivX/XviD) nemusíte použít tento filtr.

Tento filtr pracuje jako tato avs funkce:

    function PseudoMT(clip c,string filter)
    {
    a=eval("c.crop(0,0,src.width/2,src.height)."+filter)
    b=eval("c.crop(src.width/2,0,src.width/2,src.height)."+filter)
    stackhorizontal(a,b)
    }

Jediný rozdíl je, že a i b jsou vykonány paralelně a je možné rozdělit snímek do více než 2 kusů. Pokud filtr pracuje s výše uvedeným skriptem měl by pracovat s MT , pokud je filtr vláknově bezpečný (thread safe). Dust nepracuje se skriptem výše, takže jestliže chcete použít iip , použijte jiný odšumovač nebo donuťte Steadyho opravit chybu.

#### Omezení

Aby filtr běžel, musí přijímat jen jeden vstupní klip a tím je last. Filtr by také neměl počítat s obsahem celého snímku (jako smart deinterlacery) jinak je zde riziko, že bude zpracována jen část snímku. Filtr by měl být také vláknově bezpečný. Většina filtrů je vláknově bezpečná, ale některé budou vytvářet chybné výsledky nebo budou padat.

#### Instalace

Zkopírujte mt.dll do složky avisynth pluginů a zkopírujte zahrnutý soubor avisynth.dll do vaší složky windows\system32 nebo tam, kde je umístěn váš původní avisynth.dll a nezapomeňte si tento starý soubor avisynth.dll (přejmenovat) pokud nemáte nainstalovanou verzi 2.6 .

Od verze 0.7 jsou zahrnuty také další dva filtry:

- MTi() který vytváří dvě vlákna a nechá každé vlákno zpracovat jedno pole před jejich spojením jako tato avs funkce

    function PseudoMTi(clip c,string filter)
    {
    a=eval("c.AssumeFieldBased().SeparateFields.selecteven()."+filter)
    b=eval("c.AssumeFieldBased().SeparateFields.selectodd()."+filter)
    interleave(a,b).weave()
    }

Jako další pseudoskript a i b jsou vykonány paralelně. Všimněte si, že jsou vytvořena jen dvě vlákna, takže využije jen dvě (virtuální) jádra.

- MTsource() který se používá pro běh zdrojových filtrů vícevláknově (multithreaded). Pracuje jako toto:

    function PseudoMTsource(string filter)
    {
    SetMTmode(2)
    eval(filter)
    SetMtmode(0)
    }

Tedy na rozdíl od dvou ostatních filtrů je to časový (temporal) filtr který přenáší snímky vpřed v čase a ukládá je do vyrovnávací paměti (cache) pro rychlé znovuzískání.

### Syntaxe

#### MT

`MT`(clip clip,string filter,int threads,int overlap,bool splitvertical)

Všechny parametry jsou jmenné. Parametry jsou:

clip clip = last
Vstupní klip.

filter string = nemá výchozí hodnotu
Filtr, který má běžet na více vláknech. Všimněte si, že filtr nesmí měnit jak výšku tak ani šířku snímku (ale barevné prostředí je okay) a je povolen jen 1 vstupní klip. Může to být jakýkoli vestavěný filtr, avs skriptem definovaný filtr nebo externí plugin filtr dokud jsou dodržena omezení.

threads int = 2
Počet pracovních vláken. Nastavte ho na počet vláken která mohou na vašem počítači běžet současně.

overlap int = 0
- počet pixelů pro přidání na horní a spodní okraj nebo levý a pravý okraj. Zvyšte ho pokud vidíte artefakty v místě kde je snímek rozdělen.

splitvertical bool = false
- pokud je true , snímky jsou rozříznuty vertikálně(a filtru je umožněno změnit výšku) jinak je rozříznut horizontálně (a filtru je umožněno změnit šířku).

#### MTi

`MTi`(clip clip,string filter)

Všechny parametry jsou jmenné. Parametry jsou:

clip clip = last
Vstupní klip. Musí mít výšku dělitelnou 2 pro RGB a YUY2 barevná prostředí a výšku dělitelnou 4 pro YV12 barevné prostředí

filter string = nemá výchozí hodnotu
Filtr, který má běžet na více vláknech. Všimněte si, že filtr může měnit jak výšku tak i šířku snímku ve stejném čase, ale je povolen jen 1 vstupní klip. Může to být jakýkoli vestavěný filtr, avs skriptem definovaný filtr nebo externí plugin filtr dokud jsou dodržena omezení.

#### MTsource

`MTsource`(string filter,int delta,int threads,int max_fetch)

Všechny parametry jsou jmenné. Parametry jsou:

filter string = nemá výchozí hodnotu
Zdrojový filtr, který má běžet na více vláknech. V současnosti jsou podporovány pouze vnitřní a externí zdrojové filtry (jako DirectShowSource, Avisource, MPEG2Source) . Můžete použít avs skriptem definovaný filtr nebo ne-zdrojový filtr, ale to může spadnout nebo vytvářet poškozené snímky.

delta int = 1
Toto je kolik snímků je mezi každým požadavkem o snímek, takže pokud hodláte číst jen každý druhý snímek nastavte ho na 2 nebo pokud čtete snímky zpětně, nastavte ho na -1. Komplexnější modely přístupu ke snímku jako SelectEvery(10,3,6,7) nejsou podporovány (ale mohly by ostatně pracovat, protože žádané snímky jsou ve vyrovnávací paměti (cache), kde bude prostor v paměti od nevyžadovaných snímků v cache)

threads int = 2
Počet pracovních vláken. Nastavte ho na počet vláken, která mohou na vašem počítači běžet současně.

max_fetch int = 30
Toto je maximální počet snímků vpřed od aktuálně žádaného snímku, který MTsource přenese. Jeho nízké nastavení nechá vlákna nečinná po času a příliš vysoké nastavení zabere příliš mnoho paměti.

### Příklady

obyčejné rozmazání:

    MT("blur(1)",2,2)

také uživatelem definovaná funkce (používá variableblur):

    MT("unsharp(2,0.7)",2,2)

    function unsharpen(clip c,float variance,float k)
    {
    blr=binomialBlur(c,vary=variance,varc=2,Y=3,U=2,V=2)
    return yv12lutxy(blr,c,"y x - "+string(k)+" * y +",y=3,u=2,v=2)
    }

Toto sice nevytvoří zamýšlený výsledek - urychlení, ale ukáže kdy použít trojité uvozovky - když už jsou nějaké použité v parametru:

    MT(""" subtitle("Doh") """,4,0)

Příklad MTi

    MTi("fft3dfilter()")

vytváří téměř stejný výsledek jako

    MT("fft3dfilter(interlaced=true)",threads=2)

ale pro filtry, které nativně nepodporují prokládaný obsah může být jednodušší použít MTi()

Příklad pro MTsource()

    ir=MTSource(""" imagereader("c:\test.png") """,delta=1,threads=2,max_fetch=10)
    as=MTSource(""" avisource("c:\test.avi") """,delta=-1) #delta záporné kvůli reverse()
    ms=MTSource(""" MPEG2Source("c:\test.d2v") """,delta=9) #delta je 9 kvůli selectevery(9,1)
    stackhorizontal(ir.trim(0,100),as.reverse().trim(0,100),ms.selectevery(9,1).trim(0,100))

### Seznam změn

       * 0.1 first release.
       * 0.2 Should be more thread safe.
       * 0.21 forgot to comment out a Sleep(0)
       * 0.25 Added the splitvertical option
       * 0.3 More stable(and slower)
       * 0.4 Includes a custom version of avisynth 2.56 beta that should speed things up
       * 0.41 Minor speed increase
       * 0.5 Requires the included modified avisynth 2.5.6 or avisynth 2.6
       * 0.6 Bugfix: height can be changed with splitvertical=true without crashing. Also includes modified avisynth MT 2.5.7.3
       * 0.7 two new filters: MTi(), MTsource() and Avisynth MT 2.5.7.5

## Modifikovaný avisynth MT 2.5.7.5

### Úvod

Obsahuje dvě nové funkce `SetMTMode()` a `GetMTMode()` a je potřeba MT.dll. Nainstalujte ho nahrazením avisynth.dll ve vaší složce c:\windows\system32 (a pamatujte nejdříve na zazálohování starého souboru).

Poznámka: Ani oficiální verze Avisynthu 2.5.8 nepodporuje multhreading a tak vznikají pobočné pokusy o jeho vytvoření. Najdete je zde http://forum.doom9.org/showthread.php?t=144852 a nebo zde http://forum.doom9.org/showthread.php?t=148117

#### Technické info

Tyto funkce umožňují avisynthu použít více než jedno vlákno při zpracování filtry. To je užitečné, když máte více než jedno cpu/jádro nebo hyperthreading. Tato funkce je stále experimentální.

### Syntaxe

`GetMTMode`(bool threads)

threads bool = false
Když je true `GetMTMode` vrací počet využitých vláken, jinak je vrácen režim mode (viz níže).

`SetMTmode`(int mode,int threads)

Umístěte toto na první řádek v avs souboru, aby jste zapnuli časový - temporal (to je, že je zpracováno více než jeden snímek ve stejném čase) multithreading. Použijte ho později ve skriptu pro změnu režimu mode u filtrů níže.

mode int (2, výchozí 1-6)
- existuje 6 režimů 1 až 6.

       * Mode 1 je nejrychlejší, ale pracuje jen s několika filtry
       * Mode 2 by měl pracovat s většinou filtrů, ale využívá více paměti
       * Mode 3 by měl pracovat s některými z filtrů, které nepracují v režimu mode 2 ale je pomalejší
       * Mode 4 je kombinací mode 2 a 3 a měl by pracovat s ještě více filtry, ale je ještě pomalejší a využívá ještě více paměti
       * Mode 5 je nejpomalejší(Pomalejší než bez použití SetMTMode) , ale měl by pracovat se všemi filtry, které nevyžadují lineární frameserving (to je snímky přichází v pořadí snímek 0,1,2 ... poslední)
       * Mode 6 je upravený mode 5 , který by mohl být mírně rychlejší

Podrobnější vysvětlení různých režimů si můžete přečíst zde: MT modes explained

threads int = 0
Počet použitých vláken. Nastavte na 0 pro jeho nastavení na počet dostupných procesorů. Není možné měnit počet vláken jinak než v prvním SetMTMode.

### Příklad:

    SetMTMode(2,0) #zapne multihreading použitím thread = na počet dostupných procesorů a mode 2
    LoadPlugin("...\LoadPluginEX.dll") #potřebný pro načtení avisynth 2.0 pluginů
    LoadPlugin("...\DustV5.dll") #Načte Pixiedust
    import("limitedsharpen.avs")
    src=AVIsource("test.avi")
    SetMTMode(5) #mění mode na 5 pro řádky níže
    src=src.converttoyuy2().PixieDust()#Pixiedust potřebuje mode 5 aby fungoval.
    SetMTMode(2) #mění mode zpět na 2
    src.LimitedSharpen() #protože LimitedSharpen pracuje s mode 2 dobře
    subtitle("Pocet pouzitych vlaken: "+string(GetMTMode(true))+" Aktualni MT Mode: "+string(GetMTMode())) #Zobrazí mode a počet použitých vláken

### Jak vyvíjet vláknově bezpečné (threadsafe) filtry

Není zaručeno žádné lineární pořadí snímků (kromě případu kdy je použito MT místo setmtmode) a pro každý režim mode existují různá omezení:

- Mode 1: veškeré přístupy do třídy proměnných, globálních proměnných a statických proměnných musí být vláknově bezpečné použitím vhodného uzamčení (Enter/LeaveCriticalSection atd, uzamčení nepotřebují proměnné jen pro čtení (readonly)), protože více než 1 vlákno může přistoupit k třídě instancí v čase.

- Mode 2: přístup k třídě proměnných nemusí být vláknově bezpečný, protože existuje jen 1 instance třídy na vlákno. Všechny přístupy ke globálním/statickým proměnným musí být vláknově bezpečné. Protože každá třída instance zpracovává jen každý další snímek internal caches (to je cache uvnitř filtru), nepracovala by dobře. Vytvořil jsem PClipLocalStorage pro sdílení pointer mezi různými instancemi filtru.

- Mode 3: Je povoleno jen 1 vlákno pro vykonání kódu z filtru ve stejném čase. Když je vyzváno child->GetFrame , jiné vlákno může vzít filtr a vykonat kód. To znamená, že třída proměnných/globálních proměnných/statických proměnných by měla být přiřazena pro nějaké hodnoty před po tom, kdy bylo voláno lastchild->GetFrame. Místo proměnných lokální funkce by mělo být použito něco takovéhoto:

    PVideoFrame __stdcall AdjustFocusV::GetFrame(int n, IScriptEnvironment* env) {
    PVideoFrame frame = child->GetFrame(n, env);
    //Assigned to a local variable so this will work in mode 3
    env->MakeWritable(&frame); if (!line) line = new uc[frame->GetRowSize()+32];
    uc* linea = (uc*)(((int)line+15) & -16);// Align 16
    uc* buf = frame->GetWritePtr();
    int pitch = frame->GetPitch();
    int row_size = vi.RowSize();
    int height = vi.height;
    memcpy(linea, buf, row_size); // First row - map centre as upper
    if ((pitch >= ((row_size+7) & -8)) && (env->GetCPUFlags() & CPUF_MMX))
    {
     AFV_MMX(linea, buf, height, pitch, row_size, amount); }
    else
    {
     AFV_C(linea, buf, height, pitch, row_size, amount); }
    return frame;
    }

Ale ne jako toto:

    PVideoFrame TemporalSoften::GetFrame(int n,IScriptEnvironment* env) {
    __int64 i64_thresholds = 0x1000010000100001i64;
    int radius = (kernel-1) / 2 ;
    int c= 0;
    // Just skip if silly settings
    if((!luma_threshold)&& (!chroma_threshold) || (!radius))
      return child->GetFrame(n,env);
    for(int p= 0;p<16;p++) planeDisabled[p]=false;
     for(p= n-radius;p<=n+radius;p++)
      {
       frames[p+radius-n] = child->GetFrame(min(vi.num_frames-1,max(p,0)), env);
       //GetFrame assigned to class variable frames. This wouldn't work with Mode 3
       //because the next thread that enters this getframe will overwrite the result
       // from the last thread }
      //do stuff
      }

Ale při použití mode 3 není žádná potřeba pro vláknově bezpečný přístup do třídy proměnných. A protože je jen 1 instance třídy, která zpracuje všechny snímky, internal caches bude pracovat mnohem lépe. Horší věc je, že vykonat filtr v čase může jen 1 vlákno, takže pokud je to jen pomalý filtr ve skriptu, urychlení by nebylo tak velké.

- Mode 4: kombinace mode 2 a 3 takže je to okay pro přiřazení třídy proměnných před výzvou lastchild->getframe , protože je jedna třída instance na vlákno, ale problém s internal cache je stejný jako u mode 2.

- Mode 5: Bez omezení.

- Mode 6: Mírně upravená verze mode 5 , která může být trochu rychlejší.

PClipLocalStorage

Zde je příklad jak může být použit PClipLocalStorage pro sdílení cache mezi více instancemi (které jsou vytvořeny pomocí mode=2,4):

    class Cache
    {
    public: //These function should be threadsafe. The most simple way is to use
     a //critical section like
     this PVideoFrame GetCachedFrame(int
     framenumber)
     {
      EnterCriticalSection(&cs);
      //Code

      //...
      LeaveCriticalSection(&cs);
      return retval;
     } SetCachedFrame(PVideoFrame
    frame);
    private:
     CRITICAL_SECTION cs;
    }

    class Sample : public GenericVideoFilter{
    public:
     Sample(PClip _child, IScriptEnvironment* env);
     ~Sample();
     PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
    protected:
     PClipLocalStorage cls;
     Cache* FrameCache;
    }

    Sample::Sample(PClip _child, IScriptEnvironment* env)
    :
    GenericVideoFilter(_child),cls(env)
    { //if the cache has not been created yet GetValue will return 0
     if(cls->GetValue()==0) {
     //create the cache and save the address in the PClipLocalStorage
     FrameCache =  new
     Cache();cls->SetValue(static_cast(FrameCache));
     }
     // The cache has been created so assign the address to FrameCache
     else  {
     FrameCache=static_cast(cls->GetValue());
     }
    }

    Sample::~Sample()
    {
    //only delete FrameCache if it is not delete yet.
    if(cls->GetValue()!=0)  {
     delete FrameCache;
     cls->SetValue(0);//Signal that the cache is deleted
     }
    }

## Odkazy

stránky filtrů od tsp

oficiální vlákno na doom9.org forum Čtěte prosím tuto stránku a stránku podpory níže před tím než se budete ptát na pomoc - díky.

MT stránka podpory

Získáno z"http://avisynth.org/mediawiki/MT"

`Český překlad:2.7.2009`