Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: beer 21. 02. 2018, 12:32:59

Název: Paralelní zpracování souboru
Přispěvatel: beer 21. 02. 2018, 12:32:59
Ahoj, vytvořil jsem si soubor pro optimalizaci obrázků na web serveru. Konfigurační příklady, které jsem na webu našel, byly velmi neefektivní, protože jedou jen v jednom vlákně a zkouší i soubory, které již byly optimalizovány.

Napadlo mne, že by bylo efektivnější obrázky nejprve seřadit dle velikosti a zařadit do fronty. To mi jakžtakž funguje, ale jen na jednom stroji s debianem 9, na ubuntu 17.10 mám chybové hlášky o tom, že to někde nemá ve složce přístup (zkoušel jsem do /tmp přesunout pár obrázků a zkoušel to tam), obrázky se ale v /tmp neoptimalizovali, přitom jsem použil stejný postup jako na web serveru mujscript.sh /tmp/.

Koukal jsem na nějaké příklady paralelního zpracování, ale moc se v tom neorientuji. Koukal jsem i na program Parallel, ale ne že bych z toho byl zrovna moudrý.

Zde je můj současný skript:

Kód: [Vybrat]
#!/bin/bash
target="$1"

jpgfronta="$(mktemp)"
pngfronta="$(mktemp)"

find "${target}/" -type f -iname *.jp*g -exec du -a {} + | sort -n -r | cut -f 2 >"$jpgfronta"
find "${target}/" -type f -iname *.png -exec du -a {} + | sort -n -r | cut -f 2 >"$pngfronta"

while read line
do
printf "%s\n" "$line"
jpeg-recompress -q medium -l 128 -a -c -m smallfry "$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")"
done < "$jpgfronta" &

while read line
do
printf "%s\n" "$line"
optipng -quiet -o7 "$(printf "%s\n" "$line")"
done < "$pngfronta" &

rm "$jpgfronta"
rm "$pngfronta"

exit

Myslím, že by bylo efektivnější, kdyby se zpracovávali najednou soubory dle počtu jader, jedno jádro by se nechalo nevyužité. Ve frontě jsou názvy souborů pro zpracování, v jednom sloupci. Možná by bylo jednodušší soubor rozdělit do sloupců dle počtu jader -1 a zpracovávat po řádku. Na to jsem nějaký skript na webu viděl, ale nevím jak na to. Nebo prostřednictvím toho paralelu nebo xargs.

Poradí někdo, jak docílit paralelního zpracování s větší prioritou zpracování pro velké soubory?
Název: Re:Paralelní zpracování souboru
Přispěvatel: adsfasdfasdfasdf 21. 02. 2018, 13:11:43
ja bych se s tim vubec tak slozite nesral.
udelej si vypis (obrazkovych) souboru s vystupem do textoveho souboru: ls *.jpg > soubory,txt

soubor.txt rucne rozsekej na x kusu, podle toho kolik mas jader na tolik souboru: soubor1.txt, soubor2.txt.....souborX.txt

udelej si shel skript, ktery projizdi textovy soubor a z nazvu souboru (obrazku) v souborN.txt projedes fajly a zpracujes obrazky.

spustis skript x-krat:

./zpracovani soubor1.txt &> /dev/null &
./zpracovani soubor2.txt &> /dev/null &
./zpracovani souborX.txt &> /dev/null &

a nemusim vymyslet paralelni kraviny.
na prioritizaci kdyz zpracovavat male nebo velke obrazky se taky vyprdni. az ty skripty dojedou, tak dojedou.

Název: Re:Paralelní zpracování souboru
Přispěvatel: adsfasdfasdfasdf 21. 02. 2018, 13:13:21
ja jsem si takhle jednoduse kdysi v praveku na pocitacovem clusteru graboval cd a wav do mp3.
Název: Re:Paralelní zpracování souboru
Přispěvatel: Ondrej Nemecek 21. 02. 2018, 13:14:32
Udělal bych to pomocí nástroje
Kód: [Vybrat]
make. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 21. 02. 2018, 13:39:45
Udělal bych to pomocí nástroje
Kód: [Vybrat]
make. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).

Ten předpoklad na mém malém web serveru nelze splnit. Uživatel nahraje obrázek, wordpress z toho obrázku udělá x dalších obrázků - například:

uživatel nahraje
centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc.jpg (http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc.jpg)

a wordpress udělá:
(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-150x107.jpg)

(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-230x230.jpg)

(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-270x270.jpg)

(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-300x214.jpg)

(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-606x300.jpg)

(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc-606x350.jpg)

(http://centruminvestic.cz/wp-content/uploads/2018/02/electrum-ltc.jpg)

Navíc kdyby se optimalizovalo do jiné složky, nezobrazoval by se na webu optimalizovaný obrázek. Rovněž je potřeba na serveru šetřit místem.

ja bych se s tim vubec tak slozite nesral.
udelej si vypis (obrazkovych) souboru s vystupem do textoveho souboru: ls *.jpg > soubory,txt

soubor.txt rucne rozsekej na x kusu, podle toho kolik mas jader na tolik souboru: soubor1.txt, soubor2.txt.....souborX.txt

udelej si shel skript, ktery projizdi textovy soubor a z nazvu souboru (obrazku) v souborN.txt projedes fajly a zpracujes obrazky.

spustis skript x-krat:

./zpracovani soubor1.txt &> /dev/null &
./zpracovani soubor2.txt &> /dev/null &
./zpracovani souborX.txt &> /dev/null &

a nemusim vymyslet paralelni kraviny.
na prioritizaci kdyz zpracovavat male nebo velke obrazky se taky vyprdni. az ty skripty dojedou, tak dojedou.



Je to na webserveru, kde to script spouštím cronem. To ruční rozsekání je pro mne problém. Dejme tomu, že tam mám 4 jádra a chtěl bych tedy vždy spouštět 3x.
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 21. 02. 2018, 13:46:38
Udělal bych to pomocí nástroje
Kód: [Vybrat]
make. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).

Mrknu na to, není to ale kanón na vrabce? A makem lze soubor po řádcích rozdělit na stejně velké části?
Název: Re:Paralelní zpracování souboru
Přispěvatel: Jano 21. 02. 2018, 14:32:34
Skus pozriet aj https://ninja-build.org/
Na tej stranke je aj zoznam generatorov konfigurakov (napr. kniznica pre python).
Cize napises subor build.ninja, kde budu napisane pravidla ako sa optimalizuju obrazky, a zoznam obrazkov,
a on ti to pospusta paralelne (bud mu povies kolko jadier alebo si tipne sam).
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 21. 02. 2018, 14:50:36
Vypadá to zajímavě, ale asi další kanón na vrabce. Ono se ti to řekne jednoduše, napíšeš si soubor build.ninja :-).

Rád bych šel cestou vrstvení standardních jednoúčelových nástrojů, aby to bylo čitelné pro mne i pro ostatní. Spočítání řádků přes wc, spočítání kolik odříznout kam přes dc, a pak případně použít head, tail či sed na vytvoření 3 různých front a & je hodit na pozadí.

Zkusím metodou pokus omyl :-).
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 21. 02. 2018, 15:52:46
Nejjednodušší by bylo asi použití xargs, ale neumím to

zkusil jsem nahradit
Kód: [Vybrat]
while read line
do
printf "%s\n" "$line"
jpeg-recompress -q medium -l 128 -a -c -m smallfry "$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")"
done < "$jpgfronta" &

tímto:
Kód: [Vybrat]
while read line
do
printf "%s\n" "$line"
"$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")" | xargs --max-args=1 --max-procs=3 jpeg-recompress -q medium -l 128 -a -c -m smallfry
done < "$jpgfronta"

Ale mám tam nějakou chybu, obrázky to spouští jako spustitelné soubory a nepředává to cesty.
Název: Re:Paralelní zpracování souboru
Přispěvatel: nalogmulti 21. 02. 2018, 17:01:25
A co třeba jen tevřít obrázky (případně přes search parametricky najít/filtrovat) v xnview a dát hromadnou konverzi?Mám ocit, že program nevyužívá jádra CPU. Případně Zoner Photo studio, zdarma

ja jsem si takhle jednoduse kdysi v praveku na pocitacovem clusteru graboval cd a wav do mp3.
Jakože jednotlivé thready ripovaly jednotlivé skladby?
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 21. 02. 2018, 17:07:04
A co třeba jen tevřít obrázky (případně přes search parametricky najít/filtrovat) v xnview a dát hromadnou konverzi?Mám ocit, že program nevyužívá jádra CPU. Případně Zoner Photo studio, zdarma

Používám Debian a Ubuntu. Na serveru nemám grafické prostředí.

ja jsem si takhle jednoduse kdysi v praveku na pocitacovem clusteru graboval cd a wav do mp3.
Jakože jednotlivé thready ripovaly jednotlivé skladby?
Nemůžu mluvit za adsfasdfasdfasd, ale řekl bych, že určitě takhle ne, laser bývá v mechanikách jen jeden. Spíše rippování do wavu v jednom vláknu a paralelní konverze všech wavů potom do komprimovaného formátu.
Název: Re:Paralelní zpracování souboru
Přispěvatel: trubicoid2 21. 02. 2018, 17:23:50
Nejjednodušší by bylo asi použití xargs, ale neumím to

zkusil jsem nahradit
Kód: [Vybrat]
while read line
do
printf "%s\n" "$line"
jpeg-recompress -q medium -l 128 -a -c -m smallfry "$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")"
done < "$jpgfronta" &

tímto:
Kód: [Vybrat]
while read line
do
printf "%s\n" "$line"
"$(printf "%s\n" "$line")" "$(printf "%s\n" "$line")" | xargs --max-args=1 --max-procs=3 jpeg-recompress -q medium -l 128 -a -c -m smallfry
done < "$jpgfronta"

Ale mám tam nějakou chybu, obrázky to spouští jako spustitelné soubory a nepředává to cesty.

ten jpeg-recompress žere dva stejný argumenty?

přes rouru pošleš jen jeden a pak xargs -I{} a použiješ {} tam, kde chceš ty argumenty

další možnost je gnu parallel, ale xargs toto zvládne dobře a je všude
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 21. 02. 2018, 17:29:54
žere, jsou povinné, zdrojový a cílový soubor. Když je to stejné, tak se optimalizuje soubor za běhu a zapíše se změna jen v případě, že soubor nebyl již optimalizovaný předtím, jpeg-recompress to řeší přidáním poznámky do metadat a při dalším spuštění nad stejným souborem soubor jednoduše přeskočí. Na rozdíl od optipng, to je hrozná brzda, která se snaží optimalizovat již optimalizované.

Vyzkouším, díky
Název: Re:Paralelní zpracování souboru
Přispěvatel: to_je_jedno 21. 02. 2018, 19:43:20
a co kdybys proste misto GD pouzil ve WP imagick pro generovani nahledu a dal mu patricne parametry?
Název: Re:Paralelní zpracování souboru
Přispěvatel: Ondrej Nemecek 21. 02. 2018, 20:20:11
Udělal bych to pomocí nástroje
Kód: [Vybrat]
make. Příkladů musí být na internetu tuny, umí i paralelní zpracování.
Předpokladem je, že optimalizované verze budou v jiném adresáři (nebo budou odlišené názvem).

Ten předpoklad na mém malém web serveru nelze splnit. Uživatel nahraje obrázek, wordpress z toho obrázku udělá x dalších obrázků - například:

Můžete udělat nějaký „značkovací“ soubor. Dejme tomu, že obrázek bude třeba IMG_001.JPG, vy ho zoptimalizujete a uděláte soubor např. IMG_001.DONE, podle kterého pak make sám pozná, že už nemá na IMG_001.JPG sahat, pokud není JPG novější než DONE.

Kanón na vrabce to asi není, make je přesně ten jednoúčelový nástroj, který dělá dobře, co má:

Kód: [Vybrat]
# Makefile:

SRCDIR   := .
SRCFILES := $(wildcard $(SRCDIR)/*.jpg)
TRGFILES := $(patsubst $(SRCDIR)/%.jpg,$(SRCDIR)/%.done,$(SRCFILES))

all: $(SRCFILES) $(TRGFILES)
#   @echo "Make $@: from: $?";

%.done : %.jpg
    @echo "Make: $@ from: $?";
    @echo "*** Here you should optimalize: $? ***"                                                                                                           
    @touch $@;

clean:
    @rm -vf $(TRGFILES);

#eof

Použití:

Kód: [Vybrat]
make clean # odstranit .done soubory
make all # zpracovat obrázky
make all -j 3 # toto by mělo spustit 3 paralelní úlohy
Název: Re:Paralelní zpracování souboru | vyřešeno
Přispěvatel: beer 22. 02. 2018, 02:42:32
Tak snad vyřešeno. S tím xargem mi to nešlo, parallel vypadá jednodušeji.


Aktuální verze skriptu:



Kód: [Vybrat]

#!/bin/bash
target="$1"


jpgfronta="$(mktemp)"
pngfronta="$(mktemp)"


find "$target" -type f -iname *.jp*g -exec du -a {} + | sort -n -r | cut -f 2 >"$jpgfronta"
find "$target" -type f -iname *.png -exec du -a {} + | sort -n -r | cut -f 2 >"$pngfronta"


cat "$jpgfronta" | parallel jpeg-recompress -q medium -l 128 -a -c -m smallfry \{} \{}
cat "$pngfronta" | parallel optipng -o7  \{} \{}


rm "$jpgfronta"
rm "$pngfronta"


exit


Funguje to pěkně rychle. Narozdíl od doplňků je to univerzální, nasadím to i na databázi fotek, protože opticky nepoznám rozdíl v kvalitě. A proč používám jpeg-recompress? Je to založené na mozjpeg od mozilly a asi nic efektivnějšího aktuálně není. Google má tuším něco podobného, ale to jsem nezkoušel.
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 22. 02. 2018, 09:02:33
Tak funguje to napůl. Na debianu 9 bez problémů, na destkopu s ubuntu to taky dokáže vytížit na 100 % všechna jádra, ale bez jakéhokoliv výpisu a výsledek nikde. I když odstraním ty zpětná lomítka. V htopu vidím, že to něco dělá, ale žádný výstup a pořád nad stejnými soubory.
Název: Re:Paralelní zpracování souboru
Přispěvatel: Ondrej Nemecek 22. 02. 2018, 14:25:54
Ale když to pustíte znovu, bude to opět zpracovávat stejné soubory, ne? Takže když tam přibudou nějaké nové soubory, budete je zpracovávat zase všechny?
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 24. 02. 2018, 13:41:46
Když zakomentuji png, tak to projde jen od největších jpg a vyčte si to z poznámky, že ten daný soubor to již zpracovávalo a dál ho nezpracovává.

Tak funguje to i na desktopu s Ubuntu, ale protože tam mám hodně velké soubory - obrázky, které mají poměrně dost megabajt, tak se zdá, jako kdyby to pořád pracovalo a nic se neděje. Ale pak už je to lepší. Nejhorší je to u skenů, u klasické fotky cca 5 MB trvá optimalizace pár minut.

Horší je, že narozdíl od severu na desktopu někdy stroj zamrzne, když se na něm dělá něco jiného. Přece jen je desktop starší a má jen dvě jádra. Kdybych odstranil -l 128 tak by to bylo mnohem mnohem rychlejší, ale ne s tak dobrými výsledky.
Název: Re:Paralelní zpracování souboru
Přispěvatel: Ondrej Nemecek 24. 02. 2018, 15:36:49
Když zakomentuji png, tak to projde jen od největších jpg a vyčte si to z poznámky, že ten daný soubor to již zpracovávalo a dál ho nezpracovává.

Tuhle funkcionalitu ve Vašem skriptu nevidím, podle mě to zpracovává znovu všechno. A to seřazení podle velikosti je k čemu?
Název: Re:Paralelní zpracování souboru
Přispěvatel: beer 24. 02. 2018, 16:47:39
To je interní funkcionalita jpeg-recommpress, bohužel optipng to nemá.

Kód: [Vybrat]
optimages2.sh Obrázky/
File already processed by jpeg-recompress!
Metadata size is 15kb
smallfry at q=67 (40 - 95): 97.331100
smallfry at q=81 (68 - 95): 99.249321
smallfry at q=88 (82 - 95): 100.479576
smallfry at q=92 (89 - 95): 101.507240
smallfry at q=94 (93 - 95): 102.012131
smallfry at q=95 (95 - 95): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
smallfry at q=95 (95 - 94): 102.358299
Final optimized smallfry at q=95: 102.355392
New size is 58% of original (saved 1891 kb)
Metadata size is 15kb