[C#] CPU usage minder laten variëren

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Ik ben bezig aan een C# app die veel vraagt van de CPU (o.a. een FFT op duizenden punten, meerdere malen per seconde). Het tijdsverloop van het processorgebruik ziet er zo uit:

Afbeeldingslocatie: http://i2.photobucket.com/albums/y6/Bozozo/lsa_cpu_usage.png

Ik zou liever een wat constanter CPU-gebruik zien, vooral als de spikes de 100% aantikken terwijl het gemiddelde daaronder ligt. Ik vermoed dat het om GC-runs gaat... moet ik zelf zo veel mogelijk objecten vernietigen om de GC minder processortijd te laten gebruiken?

Kortom, wat kan ik doen om het CPU-gebruik constanter te krijgen?

TabCinema : NiftySplit


Acties:
  • 0 Henk 'm!

  • FireDrunk
  • Registratie: November 2002
  • Laatst online: 20:40
Kun je niet een aantalberekeningen/sec bijhouden per onderdeel... dan kan je zien waar het op welke tijd het meeste CPU kost...

Even niets...


Acties:
  • 0 Henk 'm!

  • jip_86
  • Registratie: Juli 2004
  • Laatst online: 23:17
GC runs doet het een beetje klinken als of je GC.Collect aanroept. Dat is toch niet zo hopelijk?
Als je objecten wilt vernietigen moet je zorgen dat je objecten disposed die unmanaged resources vasthouden. Bij tekenen/graphics bijvoorbeeld heb je daar veel last van.

Acties:
  • 0 Henk 'm!

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Ik weet wel waar de bottlenecks zitten... een koe van een FFT uitrekenen en een enorme grafiek naar het scherm painten :P

Ik wil niet zozeer de performance verbeteren maar eerder de load verdelen. Misschien kan ik wel een Sleep oid gebruiken om te zorgen dat de FFT en de onPaint niet vlak na elkaar worden gedaan.

edit @hierboven: ik doel op de GC runs die automatisch worden uitgevoerd. Geen idee hoevaak C# dat doet maar het leek me een goede verklaring voor de periodiciteit (~10s) in het CPU gebruik.

[ Voor 23% gewijzigd door Bozozo op 09-09-2009 20:10 ]

TabCinema : NiftySplit


Acties:
  • 0 Henk 'm!

  • urk_forever
  • Registratie: Juni 2001
  • Laatst online: 17-09 15:08
Gebruik je al meerdere threads? Je zou met background workers de FFT uit kunnen laten rekenen waarna je main thread de grafiek tekent. Misschien dat dat helpt?

Daarnaast vraag ik me af waarom je zou willen dat het CPU-gebruik constanter is?

Hail to the king baby!


Acties:
  • 0 Henk 'm!

  • jmzeeman
  • Registratie: April 2007
  • Laatst online: 12-09 16:17
Ik denk niet dat de GC zo periodiek is, maar om dat te controleren kan je GC.RegisterForFullGCNotification gebruiken om in de gaten te houden wanneer de GC aan de slag gaat en weer klaar is. Hoe actief de GC te werk gaat kan je beinvloeden met de GCSettings.LatencyModeproperty.
Persoonlijk zou ik het eerder zoeken in andere bottlenecks als IO of paging. Wel vreemd, bij FFT zou ik verwachten dat je CPU vrij constant net onder de 100% zou schommelen aangezien het voornamlijk CPU intensief is. Of wordt misschien kernel CPU tijd niet meegerekend in die grafiek (staat me heel vaag iets van bij)? dan zou je het kunnen zoeken in inter process communicatie, taskswitches of iets anders wat de kernel voor je moet doen.
Voor meer info over de GC zie: http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx.

Duidelijkere grafieken en grafieken per process en van meer eigenschappen kan je met perfmon.exe krijgen.

[ Voor 5% gewijzigd door jmzeeman op 09-09-2009 22:03 ]


Acties:
  • 0 Henk 'm!

  • Fiander
  • Registratie: Februari 2001
  • Laatst online: 28-05 12:35
Hoe ziet het grafiekje van je geheugengebruik er uit ?
als die elke 10 sec ( dat waren toch de gaten in je cpu load ) naqar beneden gaat, om daarna langzaam aan weer te stijgen, is het idd het geheugen. Is je geheugen stabiel, dan is het dat niet.
Over het algemeen word een GC run uitgevoerd waneer je een object wilt maken, welke niet meer in één stuk in het geheugen past.

Welk process heeft de cpu load? ( en kun je kernal times aanzetten ? )
mischien heb je een browserspel op de achtergrond draaien welke elke 10 sec een refresh doet ?

Deze sig is een manueel virus!! Als je dit leest heb je het. Mail dit bericht naar iedereen die je kent, en verwijder alle bestanden van je computer.


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Is dit een dedicated server voor deze app?

Zoja, what's the problem with using a server to its fullest
Zonee, heb je al uitgesloten dat andere apps niet de extra performance spike verzorgen ( as in jouw app drukt een andere app naar de achtergrond waardoor deze meer moet gaan swappen en daardoor normaal 0/1 % gebruikt en nu veel en veel meer gebruikt )

Sleeps invoegen om een rustiger cpu-beeld te krijgen zou ik nooit aan beginnen, dan koopt de klant betere hardware en dan performt jouw prog niet beter want je kunstmatige sleeps zitten er nog in. Veel plezier met aan de klant uitleggen waarom hij een investering van x in hardware heeft gedaan om het sneller te krijgen en het niet sneller is...

Maarja, ik ben dan ook zo'n persoon die zegt dat je voor een week performancedebuggen goedkoper nieuwe hardware kan neerzetten.

  • Laurens-R
  • Registratie: December 2002
  • Laatst online: 29-12-2024
Maarja, ik ben dan ook zo'n persoon die zegt dat je voor een week performancedebuggen goedkoper nieuwe hardware kan neerzetten.
En de kosten van het onderhoud dat zo'n nieuwe server vereist? Volgens mij kan een weekje debuggen daar echt wel tegenop ;)

[ Voor 37% gewijzigd door Laurens-R op 10-09-2009 11:49 . Reden: quotje toegevoegd ]


  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Het is een consumenten app... dus geen dedicated servers oid.

Met de meer gedetailleerde monitor (bedankt voor de tip!) kan ik zien dat de spikes inderdaad worden
veroorzaakt door mijn programma. Verder zie ik een vrij constant geheugenverbruik en ook dingen als #GC_handles zijn constant. Ik denk dus niet dat het de GC is.

Geen idee wat het wel is though :P

[ Voor 10% gewijzigd door Bozozo op 10-09-2009 12:09 ]

TabCinema : NiftySplit


  • Laurens-R
  • Registratie: December 2002
  • Laatst online: 29-12-2024
Je zou kunnen proberen bepaalde onderdelen in je FFT algoritme te isoleren en deze (indien je meerdere cores hebt) dynamisch over de cores heen verspreiden?

Zijn er overeenkomende acties die je per sample(?) uitvoert die verder geen afhankelijkheid heeft met overige samples? Dan zou je bijv sampleverwerking overe meerdere threads kunnen uitvoeren omdat ze geen conflicterende gedeelde state gebruiken.

Je kan bijvoorbeeld kijken of elke iteratie in een loop niet in een aparte thread verwerkt kan worden en dat je naderhand alle resultaten weer samenvoegd (in de juiste volgorde!). Vraag is echter of elke iteratie die je hebt wel genoeg overhead genereerd. Anders kost het opzetten van de threads meer tijd, dan het uitvoeren van de daadwerkelijke taak. Goede threadpooling helpt hierbij.

Je kan hiervoor ook de TPL (Task Parallel Library) voor .Net gebruiken hoewel deze nu in CTP/Beta fase is. Het mooie van dit framework is dat het schalen redelijk automatisch verloopt... ongeacht of je nou op een 1,2 of 8 core systeem werkt.

[ Voor 45% gewijzigd door Laurens-R op 10-09-2009 12:33 . Reden: meer info toegevoegd. ]


  • urk_forever
  • Registratie: Juni 2001
  • Laatst online: 17-09 15:08
Misschien dat je ook even antwoord kan geven op alle andere vragen die gesteld zijn.

Daarnaast zou je je app een kunnen profilen om te kijken of je daar meer informatie uit kan halen. Je zou deze gratis profiler kunnen proberen.

Hail to the king baby!


  • Fiander
  • Registratie: Februari 2001
  • Laatst online: 28-05 12:35
Zoals EvilB2K hierboven zegt, op splitsen in gedeeltes, en per gedeelte testen hoe het reageert.

Dus alleen je FFT alog uitvoeren, zonder deze te outputen naar een bitmap.
Daarna eenmalig je FFT uitvoeren, en deze output gebruiken om continu je bitmap te genereren.

met die twee acties kun je al een begin maken met isoleren van het probleem gebied.

Welke FFT implementatie gebruik je ?
Hoe bouw je je bitmaps op ?

Bitmap.SetPixel is bijvoorbeeld niet echt vlot te noemen.

Deze sig is een manueel virus!! Als je dit leest heb je het. Mail dit bericht naar iedereen die je kent, en verwijder alle bestanden van je computer.


  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 18-09 00:02

bomberboy

BOEM!

Kan je zoals aangegeven inderdaad al eens antwoorden op de eerdere vragen. Want mij is niet echt duidelijk wat het probleem is. Zeker wat betreft het volgdende:
Bozozo schreef op woensdag 09 september 2009 @ 19:59:
Kortom, wat kan ik doen om het CPU-gebruik constanter te krijgen?
Waarom wil je dat nu eigenlijk? 1s 100% cpu gebruik lijkt me interessanter dan 3s 33%...

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Ok, ik loop alles even af.

1. Ik weet welke functies de tijd verbruiken.
2. Ik roep nergens de GC aan. Ik vroeg me af of ik dat wel zou moeten doen, maar het lijkt erop dat de GC niet voor de pieken zorgt.
3. Ik gebruik één extra thread die de waveIn buffers regelt. De rest (fft, paint) gebeurt in Main.
4. Ik wil dat het CPU gebruik constanter is omdat 100% verbruik m.i. inhoudt dat er vertraging komt in de weergave van het signaal. Als het even kan wil ik dat vermijden.
5. Met perfmon.exe zie ik dezelfde periodiciteit in processor usage.
6. Geheugengebruik is vrijwel constant
7. Het is mijn app die de cpu zo zit t pesten, geen andere apps.
8. Het programma draait niet op een dedicated server.
9. Ik gebruik de FFT van Jeff Morton (2007). Dat is Cooley-Tukey met bit-reversal.
10. Bitmaps worden getekend met de GDI+ managed code. Ik maak een array van Points en call dan drawLines(points).

Wat verwarring schijnt te zaaien is dat ik geen 100% processor usage wil. Ik zit niet met een berekening die eenmalig en zo snel mogelijk moet worden gedaan, maar met een ingangssignaal (wave) dat moet worden verwerkt en weergegeven. Uiteraard tegen zo weinig mogelijk processor usage.

edit: profilen ben ik nu mee bezig maar tot dusver geen verrassingen. De fft, het verwerken van de input buffer (o.a. opsplitsen in kanalen en van bit array naar integer array converteren) en het painten zijn de zware functies. Ik probeer nu te vinden wie de periodiciteit veroorzaakt.

[ Voor 19% gewijzigd door Bozozo op 10-09-2009 13:47 ]

TabCinema : NiftySplit


  • Laurens-R
  • Registratie: December 2002
  • Laatst online: 29-12-2024
Als je realtime weergave wilt (zoals je nu lijkt te zeggen) is het alsnog noodzakelijk om zo snel mogelijk/efficienter je verwerking te realiseren...Juist in realtime toepassingen! Zie ook mijn eerdere post om het e.e.a. met multithreading te optimaliseren. Dat geld net zo goed voor realtime FFT.

Hoe ziet de algemene strekking van je realtime loop er uit?

iets als in?:

code:
1
2
3
4
5
6
while(verwerking == true)
{
    Buffer = GetWaveInBuffer();
    Result = DoFFT(Buffer);
    DrawFFTResult(Result);
}


edit: even nog je post hierboven nogmaals door gelezen... array conversies van array type 1 naar array type 2 kosten nogal wat tijd... simpelweg omdat je enkel en alleen een loop doorloopt om elementen opnieuw te assignen/te casten.

Wellicht kan je meerdere loops samenvoegen tot 1?

Daarnaast kan je de resolututie van je grafiek wellicht omlaag bijstellen. Als er meerdere punten samenkomen op 1 pixel in de grafiek, kan je misschien de tussenliggende punten overslaan en alleen tekenen wat je ook daadwerkelijk ziet.

[ Voor 34% gewijzigd door Laurens-R op 10-09-2009 13:51 ]


  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
De code heeft inderdaad het patroon dat je daar suggereert, met twee tussenstappen:

code:
1
2
3
4
5
6
7
8
9
getWaveInBuffer(callbackFunc);

void callbackFunc(buffer)
{
  channels = getDataFromBuffer(buffer);
  ffts = FFT(channels);
  points = transformToGraphPoints(ffts);
  draw(points)
}


De buffer bestaat helaas niet uit twee arrays (channels) met integers erin. Het is een byte array met de kanalen interlaces, dus dat moet ik eerst uit elkaar peuteren en omzetten naar integers.

Profilen wijst erop dat de periodieke pieken in CPU usage worden veroorzaakt door mijn data -> graph points functie, maar niet door de bitmap bewerkingen of het tekenen van de bitmap naar de control. Ik zoek nog even verder maar ik denk niet dat ik het 'probleem' (inderdaad niet echt een ramp) niet kan verhelpen.


edit:
EvilB2k schreef op donderdag 10 september 2009 @ 13:41:
Daarnaast kan je de resolututie van je grafiek wellicht omlaag bijstellen. Als er meerdere punten samenkomen op 1 pixel in de grafiek, kan je misschien de tussenliggende punten overslaan en alleen tekenen wat je ook daadwerkelijk ziet.
Dat doe ik al :)

[ Voor 22% gewijzigd door Bozozo op 10-09-2009 14:16 ]

TabCinema : NiftySplit


  • Laurens-R
  • Registratie: December 2002
  • Laatst online: 29-12-2024
aha :)

Wat gebeurt er in die conversie? Ik snap dat het je FFT data naar punten in je grafiek toe converteerd, maar hoe ziet dat proces er uit? (in grote psuedocode lijnen)

Pas je een scale factor toe op je data waardoor het binnen de grenzen van je grafiek past?

kortom: wat voor bewerking doe je op je data om een x,y graph positie te verkrijgen?

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Topicstarter
Hmm, het is toch niet die data -> graph point functie die het doet. Als ik iets anders uitzet (bijvoorbeeld de FFT) worden de pieken ook lager. Het is gewoon de app als geheel die dit gedrag veroorzaakt, niet één functie. Hoe meer toeters en bellen ik aanzet hoe sterker het periodieke verbruik zichtbaar wordt.

Bedankt voor de hulp maar ik denk dat ik .Net maar gewoon zn periodieke dingetjes moet laten doen ;)

TabCinema : NiftySplit


  • bomberboy
  • Registratie: Mei 2007
  • Laatst online: 18-09 00:02

bomberboy

BOEM!

Bozozo schreef op donderdag 10 september 2009 @ 13:17:
Wat verwarring schijnt te zaaien is dat ik geen 100% processor usage wil. Ik zit niet met een berekening die eenmalig en zo snel mogelijk moet worden gedaan, maar met een ingangssignaal (wave) dat moet worden verwerkt en weergegeven. Uiteraard tegen zo weinig mogelijk processor usage.
Als ik het goed begrijp heb je dus een of ander signaal dat je meet door sampling ofzo? En je verwerkt op bepaalde tijdsstippen de signalen. Doordat die verwerking vrij rekenintensief is loop je het risico dat het samplen van het inputsignaal niet helemaal meer loopt zoals het zou moeten.
Correct?

Indien ja, kan je dan de applicatie eventueel niet opsplitsen in meerdere threads (voor zover dit nog niet gebeurd is) met een thread voor het samplen van het inputsignaal en een thread die de verwerking doet. De eigenlijke verwerkingsthread geef je dan een lage prioriteit en de sample-thread een hoge prioriteit.

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Bozozo schreef op donderdag 10 september 2009 @ 14:38:
Hmm, het is toch niet die data -> graph point functie die het doet. Als ik iets anders uitzet (bijvoorbeeld de FFT) worden de pieken ook lager. Het is gewoon de app als geheel die dit gedrag veroorzaakt, niet één functie. Hoe meer toeters en bellen ik aanzet hoe sterker het periodieke verbruik zichtbaar wordt.

Bedankt voor de hulp maar ik denk dat ik .Net maar gewoon zn periodieke dingetjes moet laten doen ;)
Gooi er gewoon eens een behoorlijke profiler tegenaan...

Want als je het niet op 1 punt kunt isoleren dan lijkt het sterk op een .net dingetje wat je gewoon vaker moet flushen / aanroepen. Achterhaal wat het is en flush het 10x per seconde ipv de default 1x per 10 seconde en je hebt al een rustiger cpu usage, je algemene cpu usage gaat omhoog maar je pieken verdwijnen dan wel.

Er is afaik bijna geen enkel periodiek ding in .net wat niet tussentijds te flushen / aan te roepen is
Pagina: 1