Effektiv FIFO mellan trådar/processer

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Effektiv FIFO mellan trådar/processer

Inlägg av arte »

Hej,

Jag håller på och labbar med bild kompremering i mjukvara och har där flera olika trådar/processer som kommunicerar med varandra via FIFOs.
I princip är det fem stycken block som läser in data från en FIFO och sedan skickar till nästa block - altså seriekopplade.
Ifall en FIFO är tom så får det blocket/modulen vänta tills den har fått någon data.

Jag funderar på att använda mig av linux-FIFOs och undrar ifall någon vet hur prestandan är på dessa?
jbulow
Inlägg: 114
Blev medlem: 22 juni 2006, 21:35:26
Ort: Malmö

Re: Effektiv FIFO mellan trådar/processer

Inlägg av jbulow »

Prestanda jämfört med vad? Annars är svaret "en FIFO är jättesnabb".
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Effektiv FIFO mellan trådar/processer

Inlägg av sodjan »

Vad är "linux-FIFOs" och vad har det i "Mikroprocessorer" att göra ?
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Effektiv FIFO mellan trådar/processer

Inlägg av arte »

jbulow skrev:Prestanda jämfört med vad? Annars är svaret "en FIFO är jättesnabb".
Hehe jo det skulle jag kanske skrivit. Jämfört med en t.ex lokal socket eller andra alternativ för IPC.

Antar att de är jätte snabba (som du skrev). Om man skapar de på en RAM disk borde de ju vara jätte snabba, undrar mest om det är mycket overhead att skriva till en sådan.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Effektiv FIFO mellan trådar/processer

Inlägg av arte »

sodjan skrev:Vad är "linux-FIFOs" och vad har det i "Mikroprocessorer" att göra ?
Named PIPES och det körs på en mikroprocessor....(just nu en Core 2 Duo :) )
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Effektiv FIFO mellan trådar/processer

Inlägg av sodjan »

> undrar mest om det är mycket overhead att skriva till en sådan.

Nej. Eller Ja. Beror på hur mycket "mycket" är. :roll:

> (just nu en Core 2 Duo :) )

Aha, OK. Kanske inte en AVR/PIC, men visst, en "Mikroprocessorer" är det ju... :-)
jbulow
Inlägg: 114
Blev medlem: 22 juni 2006, 21:35:26
Ort: Malmö

Re: Effektiv FIFO mellan trådar/processer

Inlägg av jbulow »

Antar att de är jätte snabba (som du skrev). Om man skapar de på en RAM disk borde de ju vara jätte snabba, undrar mest om det är mycket overhead att skriva till en sådan.

De ska nog inte hamna i något filsystem, det verkar illa. Vissa unixar delar ett minnesblock mellan processer som används som kommunikationskanal. Overheaden är nog minsta möjliga du kan uppnå för IPC.
saxofon
Inlägg: 160
Blev medlem: 2 januari 2008, 11:32:20
Ort: Bromma

Re: Effektiv FIFO mellan trådar/processer

Inlägg av saxofon »

Hmm... det räcker nog inte bara med "jättesnabb FIFO", hela designen måste genomgående vara tweakad för performance... ;-)

Föreslår att du

* conf'ar kernel med low latency scheduler (har ingen aning om vad dina realtidskrav är
men med original kernel.org rt kommer man ofta ganska långt)

* disable'ar swap. Man vill absolut inte att kernel ska få för sig att skicka ut nåt på disk
som sedan måste läsas in i minnet igen för att kunna exekveras.

* i samband med swap disable måste man stänga av overcommit av minnet (linux tillåter
normalt allokering in absurdum av minne, det är först när man *skriver* till en page (4096
bytes minnes chunk) som det blir en fysisk allokering) sedan måste koden skrivas snyggt
förstås och alltid kolla efter NULL pekare vid minnes allokering... ;-)

Kod: Markera allt

cat 2 > /proc/sys/vm/overcommit_memory
* programmera ett gäng trådar app istället för ett gäng processer.
Iofs ifall du har en multicore CPU kan det vara intressant att ha fler än en process och
därmed kunna låsa de olika processerna till var sin core. Dessa kan ju i sin tur vara
multitrådade, men man får bättre parallellism i sin kod. ( inte helt enkelt att göra sådan
design helt optimal, man bör tänka på cache som ofta delas mellan core's tex)

* dina trådar delar du upp i lämpliga prioriteter, tex så här i början av tråden innan huvudloopen:

Kod: Markera allt

#if POSIX_RT
	struct sched_param threadsched;

	threadsched.sched_priority = 30;

	status = sched_setscheduler(0, SCHED_FIFO, &threadsched);
	if (status) {
		printf("%s: sched_setscheduler %d\n", __FUNCTION__, status);
		pthread_exit(&jog_status);
	}

	// never let us be swapped out
	mlockall(MCL_CURRENT | MCL_FUTURE);
#endif
(den sista raden behövs egentligen inte ifall man gjort det rätt från början i och med disable av swap...)

Nu mer till din fråga, hur passa data snabbt mellan trådar? Så här skulle mina val, lite snabbt nerplitat
bli, med fallande behov av snabbhet (men kanske stigande i form av enkelhet, beror ju på din nivå)

* cirkulära buffrar - i princip allokerar du innan loop'arna en bit minne som du själv får hantera
i din applikation. Snabbare än så här blir det inte i mjukvara.

(Unix IPC/FIFO/PIPES och sockets lämnar jag därhän, de är mer lämpade för kommunikation mellan processer istället för trådar...)

Det blev alltså en ganska kort lista... enbart cirkulär buffert. Gammalt, enkelt, oldschool men genialt :-)

Du hittar mycket intressant att läsa vidare på om linux advanced programming på just linux advanced programming site'n ;-)
Finns att köpa som bok eller ladda ner som pdf'er.
http://www.advancedlinuxprogramming.com

Gör man sådant här får man riktigt bra prestanda, man kan glömma tramsa runt med RTAI. 8)

EDIT: glömde förstås exempel på hur man stänger av overcommit...
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: Effektiv FIFO mellan trådar/processer

Inlägg av mri »

Prestandamässigt är säkert nån egen ringbuffer var producenten väcker upp eventuella sovande konsumenter själv med nån lämplig pthread funktion bäst, MEN, då mister man ju möjligheten att använda poll/select... vilket man ofta vill göra om applikationen nu inte bara skall tugga data.
bos
Inlägg: 2314
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: Effektiv FIFO mellan trådar/processer

Inlägg av bos »

Avdelningen för baksätesmoderering noterar: Det känns som att den här tråden hör hemma nån annanstans, förslagsvis "Mjukvara / Litteratur" eller "Allmänt".

Visst, en "Core 2 duo" är en mikroprocessor, men tråden handlar om ett antal magnituder nivåer bort från själva kretsen. Annars skulle man lika gärna kunna ställa frågor om hur man ändrar inställningar på en viss typ av mobiltelefoner då det är mikroprocessorer i dem också. Eller fråga hur man reparerar en hårddisk, det har ju också minst en processor. Eller varför inte sälja sin tamagochi här? Kanske rent av få ett nytt skal till den?
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Effektiv FIFO mellan trådar/processer

Inlägg av arte »

saxofon skrev: Nu mer till din fråga, hur passa data snabbt mellan trådar? Så här skulle mina val, lite snabbt nerplitat
bli, med fallande behov av snabbhet (men kanske stigande i form av enkelhet, beror ju på din nivå)

* cirkulära buffrar - i princip allokerar du innan loop'arna en bit minne som du själv får hantera
i din applikation. Snabbare än så här blir det inte i mjukvara.

(Unix IPC/FIFO/PIPES och sockets lämnar jag därhän, de är mer lämpade för kommunikation mellan processer istället för trådar...)
Är inte ens säkert att det kommer köras på ett riktig Linux system.
Cirkulära buffrar låter intressant..
Implementerar man detta med två pekare, en skriv och en läs. Där CPU1(producer) flyttar fram skriv pekaren och CPU2(producer) flyttar fram läspekaren?
Typ:

Kod: Markera allt

void cpu1_producer()
{ 
  while(1)
  {           
          size_left = FIFO_SIZE - (fifo.bytes_written - fifo.bytes_read);
          for(i=0;i<size_left;i++)
              mem[  i++ & (FIFO_SIZE-1)]=calc_stuff();
         ffifo.bytes_written+=size_left;
   }
}
void cpu2_producer()
{ 
  while(1)
  {
          i=size_left =  (fifo.bytes_written - fifo.bytes_read);
          for(i=0;i<size_left;i++)
              do_something( mem[i & (FIFO_SIZE-1)] );
         ffifo.bytes_read+=size_left; 
   }
}
Är ju ganska dumt att behöva kolla så att man inte överstiger FIFO storleken för varje byte.
Ren dubbelbuffring kanske är bättre då blir det väldigt lite overhead för bufferhantering?
saxofon
Inlägg: 160
Blev medlem: 2 januari 2008, 11:32:20
Ort: Bromma

Re: Effektiv FIFO mellan trådar/processer

Inlägg av saxofon »

Ah ok jag fattade det som att det skulle vara i linux (eller iallafall något unix liknande)

Tråden får gärna flyttas, mjukvara och litteratur känns fel dock...
Isåfall kanske vi ska skapa en egen sektion mjukvara, med tre huvud indelningar:
* Köpt - här diskuterar vi sådan mjukvara vi köper (cad, windows etc etc)
* opensource eller foss som man brukar kalla det - här diskuterar vi sådant vi laddat ner (cad, linux, bsd, gnu stuff etc etc)
* egethack - här diskuteras sådant vi gjort själva.

Nåja, jag är ingen polis i detta forum :badgrin:

Cirkulär buffert hantering kan väl lösas på fler sätt.
Jag brukar ha en minnesarea med viss storlek, ett index för påfyllning och ett index för avtappning.
i början är bägge index noll...
Vartefter man fyller på ökas påfyllnings-indexet, fast först kollas att påfyllningsindex inte springer förbi slutet på bufferten (isåfall ska den sättas till noll igen) samt att den inte springer om avtappnings indexet (=out of mem).
Vartefter man tappar av ökas avtappningsindexet, fast först kollas att avtappningsindex inte är lika med påfyllnings-index (=inget data att hämta) samt att den inte springer förbi slutet på bufferten (isåfall ska den sättas till noll igen).
Det kanske var något liknande som du plitade ner med din pseudo kod.
Finns allt inom samma core kan man ju köra med pekare istället (blir mer optimerad kod),
men brukas den cirkulära bufferten från flera cores så kan det vara enklare med index och
en offset till arean (som ju kan vara olika från olika cores, beror bla på om man kör synkron
eller asynkron multiprocessing)

Hur menar du med dubbelbuffring i detta sammanhang? En term som normalt brukar användas när man ritar grafik, då har man en buffert som är den aktiva synliga ritytan och en som man ritar på i bakgrunden så att säga och snabbt kan swappa mellan dessa.
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: Effektiv FIFO mellan trådar/processer

Inlägg av mri »

"Ren dubbelbuffring kanske är bättre då blir det väldigt lite overhead för bufferhantering?"

Jag hoppas du börjar med att köra profilering på din kod så du inte spenderar massa tid på att optimera överföringen mellan trådarna som kanske bara bidrar med 1% av totala CPU användningen. Bildkomprimering låter väldigt tungt jämfört med att flytta data mellan trådar...
Skriv svar