Executia bash paralel pe procesoare multicore

Executia bash paralel pe procesoare multicore
Executia bash in multicore mode !            Running bash scripts in multicore mode

More details

RO EN

 

 

Bash nu lucreaza paralel.Solutia de compromis ar fi divizarea problemei in cate nuclee avem,clonarea scriptului original in atatea clone cate nuclee + executia lor simultana.

linebreak

Caz propriu : AMD Quad core  640 la 3 Ghz. O basca de resurse as zice !

Pentru o aplicatie mai speciala , am nevoie de word processing , adica am un fisier csv cu 15 delimitari si 30 de mii de linii , si trebuie sa rearanjez coloanele dupa anumite tipare, conditii s.a.md.

Solutia de compromis a fost un program BASH care utilizeaza frecvent instructiunea "sed"

in asa fel incat fiecare linie din fisier este descompusa in coloane , si atribuie variabilelor de la a la 0 continutul coloanei.Dupa ce aceste variabile se populeaza , este simplu sa generez un alt fisier  in alta ordine,si cu alte combinatii.

Ok, am scris programul , rulez si dureaza cam 8 minute pentru ca " 1 aplicatie / 1 nucleu".

Celelalte 3 nuclee raman inactive.Cum la pun si pe ele la treaba ??

Solutie :

Numaram cate CPU avem , splitam fisierul in $cores parti egale , clonam progamul original in $cores parti ,lansam in background toate clonele, ele vor genera 2, sau 4  ( cate nuclee ai ) rezultante partiale , fiecare clona trebuie sa anunte cand este gata , punem o conditie " cand $cores mesaje sunt OK atunci combinam  rezultantele obtinute  si facem curatenie in fisierele temporare. Suna complicat ? e mai simplu decat crezi !

 

#!/bin/bash

cores=$(ls  /proc/acpi/processor/ | wc -l)
cat  TEST.csv  > fisier.tmp
sed -i '1d' fisier.tmp
file_lines=$(cat fisier.tmp | wc -l)

let "split_lines=$file_lines/$cores"
let "split_lines=$split_lines+1"
split -d --lines=$split_lines fisier.tmp CPU

( for script in `seq 1 $cores`;
do
let sufix=script-1
cat script.cfg > "CPU0$sufix.script"
chmod +x CPU0$sufix.script
sed -i 's/filenumber/CPU0'$sufix'/g' CPU0$sufix.script

./CPU0$sufix.script &
done
)

( while [ 1 ]
do
ok=$(ls ok.* | wc -l)
if [ "$ok" = "$cores" ] ; then ./script_reintregire.sh ; exit
fi
sleep 1
linii_realizate=$(cat final.CPU* | wc -l)

let procentaj=(linii_realizate*100)/file_lines
echo $procentaj
done )| zenity --width=400 --height=100 --progress --title="Procesez $file_lines articole" --text="Please wait ...parsing in progress" --percentage=0 --auto-close ;

 

in acest exemplu , script.cfg este programul de word processing ,din care se construiesc clonele,

in fiecare clona este declarata o variabila comuna care trebuie " search and replace all " dupa numele alocat clonei Ex. daca prima clona are numele script.CPU0 atunci fisierul CSV trebue impartin in asa fel incat fiecare clona sa prelucreze un fisier atribuit .

 

Reintregirea se face

date=$(date '+%d_%B_%Y')
rm final.$date final_old.csv
cat final.CPU* >> final.$date
cat final_old.* >> final_old.csv

In acest fel , daca sunt 4 nuclee ,fiecare nucleu va executa doar 1/4 din fisierul.csv de baza, timpul de executie fiind de 4 ori mai mic in acest caz.

acest exemplu se poate modifica in asa fel incat sa accepte diferite programe scrise in bash, programe de word processing, sau batch photo  resize  ( in acest caz se poate ca " convert" sa fie lansat in 4 instante simultan, si daca in folder avem 5 poze atunci splitarea = numar de poze/numar de cores + 1 (+1 este necesar pentru evitarea splitarii cu numar zecimal), clona CPU0 proceaseaza pozele de la 1 la 126, clona CPU1 proceseaza de la 127 la  253 , samd , ultima clona executa cu cateva poze mai putin. De ce ? pentru ca bash nu manipuleaza prea bine numerele zecimale, si daca imparti sa zicem 10 la 3 atunci rezultatul va fi 3, asta inseamna ca daca ai 4 cores , vei avea 5 splitari ceea ce nu este bine.daca adaugam 1 , atunci 10/3 =3 plus 1 egal 4 deci 2 splitari vor avea 4 linii egale , iar ultima bucata va avea 2 linii. Pare complicat dar nu este, daca sunteti incepatori in bash oricum rezultatul va fi un fiasco.

Mecanismul de mesagerie dintre clone, este facut cu generarea de fisiere .ok , si bucla cu verificare daca numarul de fisiere .ok este egal cu numar de cores atunci toate clonele au terminat. se putea face cu  instructiunea wait dar am preferat asa de dragul tutorialului si a controlului absolut al executiei cap coada.

La ce bun  wordprocessing"  ? ,ca dupa cum suna , poti face din Office acest lucru.

Pentru cei care au E-commerce , primesc un fisier .csv  cu produse , categorii s.a.m.d. dar fisierul este pur si simplu inutilizabil, nu are categorii cum trebuie, nu are meta description, nu are declararea de categorii dupa anumite criterii (produse de lux , sau orice alte combinatii), produs activ sau inactiv daca are imagine sau nu, si altele.

Din 15 coloane si 30 de mii de articole , eu generez 25 coloane in 1,8 minute. Poti face asta in office? in fiecare zi ? De ce nu in C++ ?

Pentru ca sunt lenes su nu am invatat prea mult C ++ !

 

 

 

 

 

True , bash aint running parallel.
still, i did wrote a piece of software script.cfg for some test.csv word processing.
bash is counting lines in that file , counting how many CPU u got, split flies/cores +1 ,clone script .cfg as many times as cores u got, "sed" some variables inside clones , make them executable and run them simultaneous. make a messaging mechanism to notify when all are done, and after that recombine partial result into a single result.
In this way , some test file having 30k lines is split in 4 parts( amd quad core) ,and each clone is processing just 1/4 of test file, thus CPU is running 100% on all cores. When finish , it combines all 4 parts into a single file.
mechanism to check out when all cores are done can be made using " wait", but for the sake of controlling ,i did it in my way.

#!/bin/bash
cores=$(ls /proc/acpi/processor/ | wc -l)
touch images.list
cat TEST.csv > fisier.tmp
sed -i '1d' fisier.tmp
file_lines=$(cat fisier.tmp | wc -l)

let "split_lines=$file_lines/$cores"
let "split_lines=$split_lines+1"
split -d --lines=$split_lines fisier.tmp CPU

( for script in `seq 1 $cores`;
do
let sufix=script-1
cat script.cfg > "CPU0$sufix.script"
chmod +x CPU0$sufix.script
sed -i 's/filenumber/CPU0'$sufix'/g' CPU0$sufix.script

./CPU0$sufix.script &
done
)

( while [ 1 ]
do
ok=$(ls ok.* | wc -l)
if [ "$ok" = "$cores" ] ; then ./script_reintregire.sh ; exit
fi
sleep 1
linii_realizate=$(cat final.CPU* | wc -l)

let procentaj=(linii_realizate*100)/file_lines
echo $procentaj
done )| zenity --width=400 --height=100 --progress --title="Procesez $file_lines articole" --text="Please wait ...parsing in progress" --percentage=0 --auto-close ;


Sorry about romanian words, aint got time to translate !

    Atribut1linebreakAtribut2linebreakAtribut3

54.204.134.183

Articole noi

No new products at this time