Välkommen till linuxportalen.se!

Linuxportalen.se är Sveriges största och aktivaste webbplats för användare av öppen- och fri programvara.

Du besöker Linuxportalen.se som gäst vilket begränsar din möjlighet att använda webbplatsens alla funktioner. Genom att registera dig som medlem får du inte bara möjlighet att söka bland webbplatsens innehåll, skapa nya och delta i befintliga diskussioner, skapa din egen blogg, kommunicera med andra medlemmar genom privata meddelanden och delta i omröstningar. Du får också tillgång till Veckans Kadavro - en seriestrip unikt skapad för Linuxportalen.se!

Registeringen sker snabbt och är helt kostnadsfri - tveka inte, bli medlem idag!

Använda flera kärnor vid skriptkörning

Kan man få till det att det här skriptet kör flera filer parallellt på flera kärnor? Fyra filer parallellt på varsin kärna vore att föredra.

Det är ett skript som skalar ner bilder mha imagemagic.

 

#/bin/sh
#
for i in "$@"; do
convert -scale 400x400 -unsharp 0.5x0.5+1.65+0.03 \
-quality 76 "$i" "400_$i"
done

 

 

 

 Tackar!

/C

 

Alternativ för kommentarvisning

Välj ditt önskade sätt att visa kommentarerna och klicka på "Spara" för att verkställa dina ändringar.

Kristians bild

Det här är lite som att be någon byta dist Wink

http://blog.doughellmann.com/2009/04/implementing-mapreduce-with.html

---------------------------------------

Open Source - because writing software doesn't make you a "traitor"

---------------------------------------

 

FoHs bild

Ett sätt är väl att använda &-operatorn. Men jag har för mig att jag läst något annat sätt att göra det på också, men jag kommer inte ihåg var. Slog lite i mina böcker och där hittade jag ingenting.

Kristians bild

Löser det verkligen problemet? Det startar väl lika många processer som det finns bilder att konvertera? Tanken här är ju att bara ha max "antal cpuer" processer igång samtidigt.

---------------------------------------

Open Source - because writing software doesn't make you a "traitor"

---------------------------------------

 

Kristians bild

En lösning är att skriva två scripts - ett som tar reda på antalet cpu:er, hackar upp listan av bildfiler och som startar "antal cpu:er":er instanser av ett andra script som processerar var sin del av listan.

I linux fungerar

NCPUS=`grep ^processor /proc/cpuinfo | wc -l`

men jag vet inte ifall det är portabelt till BSD-system

split -l infile 100 outprefix

Tar raderna i infile och fördelar de i filer om 100 rader (skapar filer enligt outprefix_aa outprefix_ab outprefix_ac osv.)

100 bör ersättas med antal bilder delat med antalet processorer

 

---------------------------------------

Open Source - because writing software doesn't make you a "traitor"

---------------------------------------

 

FoHs bild

Ja, alltså, han får ju modifiera scriptet om han ska använda den operatorn, så att det bara drar igång 4 eller så Smile

pluckers bild

Jag håller med Kristian att detta är enklare att hantera i ett annat språk (t.ex. python:), men du kanske kan använda dig av xargs. GNU xargs har en parameter -P för att ange hur många jobb den ska köra samtidigt. Ett snabbt exempel baserat på ditt skript skulle resultera i något likt följande:

#!/bin/bash

convert_image() {
  for arg; do
    convert -scale 400x400 -unsharp 0.5x0.5+1.65+0.03 \
            -quality 76 "$arg" "new/$arg"
  done
}
export -f convert_image
mkdir -p new
find . -name '*.jpg' -print0 | xargs -0 -n 1 -P 4 bash -c 'convert_image "$@"' --

Det konverterar samtliga jpg-bilder i en katalog med fyra parallella processer och sparar de konverterade bilderna i en katalog 'new'. Modifiera det enligt dina egna önskemål.

/Micke

Kristians bild

Smart Smile Kände inte till -P parametern

NPROC=`grep ^processor /proc/cpuinfo | wc -l`

find . -name '*.jpg' -print0 | xargs -0 -n 1 -P $NPROC bash -c 'convert_image "$@"' --

---------------------------------------

Open Source - because writing software doesn't make you a "traitor"

---------------------------------------

 

pluckers bild

Om processen använder en viss mängd I/O, så kan det vara en idé att starta fler processer än NPROC (t.ex. 1,5 x NPROC). Då kan en process köra medan en annan väntar på I/O.

Däremot bör det inte vara för mycket användning av en och samma I/O-resurs utan snarare råda en viss balans mellan CPU och I/O annars bör man nog snarare undvika att köra för många processer samtidigt (kanske t.o.m. allt sekventiellt). Ljudet av en hårddisk som "thrashar" är varken trevligt att lyssna på eller speciellt effektivt... Wink

/Micke

FoHs bild

Ja, det var nog xargs -P jag läste om Smile

clfns bild

tack för superbra tips!!! Det fungerar utmärkt med ditt exempel plucker och det blev snyggt med ditt tillägg med antal kärnor Kristian.

Jag fick ner tiden från ~50 sek till ~14 sekunder för samma filer.

Det som är kvar nu, som jag inte lyckades få till är att istället för att skapa en ny mapp och flytta filerna dit, vill jag behålla filerna i samma mapp och lägga till ett prefix innan filnamnet. Jag försökte på lite olika sätta men jag kunde inte. Tips det?

/C

pluckers bild

Följande borde fungera.

  for arg; do
    dirname=${arg%/*}
    prefix_arg=${arg/$dirname\//${dirname}/400_}
    convert -scale 400x400 -unsharp 0.5x0.5+1.65+0.03 \
            -quality 76 "$arg" "$prefix_arg"
  done

En trevlig bonus med denna ändring är att det nu även fungerar att konvertera filer i underkataloger Wink

/Micke

Instämmer, tack för tråd och tips, och tack för att ni finns.

För ett tag sedan skrev jag några script som hämtar KDEs kortlekar i vektorformat och splittar dem till png. Splittningen gör jag i inkscape och det tar fruktansvärt lång tid. Nu när jag har modifierat det för att använda alla kärnor så tar det bara lång tid. Och äntligen är staplarna i htop i arbete. Smile

Här är min anpassning

#!/bin/bash

split_image() {
  source almond.game.card.sh

  SVGS=${#SVG_SOURCE[@]}
  VALUES=${#VALUE[@]}
  SUITS=${#SUIT[@]}

  for arg; do
    DECK_DIR=`basename $arg .svgz`
    if [ ! -e "$DECK_DIR" ]
    then
      mkdir "$DECK_DIR"
    fi

    for (( j=0;j<$VALUES;j++)); do
      for (( k=0;k<$SUITS;k++)); do
    PNG=${VALUE[${j}]}_${SUIT[${k}]}
    inkscape -z --export-png=$DECK_DIR/$PNG.png $arg --export-id=$PNG --export-width=70
      done
    done
  done
}

export -f split_image
NPROC=`grep ^processor /proc/cpuinfo | wc -l`

find . -name '*.svgz' -print0 | xargs -0 -n 1 -P $NPROC bash -c 'split_image "$@"' --

exit 0

pluckers bild

Jag kan tänka mig att 52 anrop till inkscape för varje svgz-fil tar "lång tid" Wink Har man då flera svgz-filer så kan man nog tjäna en hel del på att köra dem parallellt.

Inte för att det kommer förändra körtiden något men

    if [ ! -e "$DECK_DIR" ]
    then
      mkdir "$DECK_DIR"
    fi

skulle du kunna ersätt med enbart

    mkdir -p "$DECK_DIR"

Lite "renare" skript...

/Micke