Eksponensiell Bevegelig Gjennomsnitt C Kode


Jeg har profilert dette ved hjelp av Visual C profiler, og det står for om lag 35 av kjøretiden. Dette eksponentielle glidende gjennomsnittet kalles mer enn trillion ganger, fordi det brukes gjentatte ganger på behandling av mer enn 400 gigabyte data. Dataene kommer ut av en Raid Level 0 solid state disk array, så leser datakontoer for mindre enn 5 av tiden. Størrelsen på prisen er rundt 100. Jeg opprinnelig økte det med en faktor 4 ved å forhåndsberegne så mye av dataene som mulig. Da var jeg i stand til å øke det igjen med en faktor ndash PaeneInsula 30 okt 11 kl 20:41 Jeg klarte å øke hastigheten igjen med en faktor på 12 ved multithreading den (datatypen er slik at den kan multithreaded i slik at lasten er perfekt balansert.) Og jeg har det kjører på en i7 990x (som har 6 kjerner, overhullet av totalt 12), overklokket. ndash PaeneInsula 30 okt 11 kl 20:51 Sikkert, multithreading kan hjelpe. Men du kan nesten sikkert forbedre ytelsen på en enkelt gjenget maskin. Først beregner du det i feil retning. Bare de mest moderne maskinene kan gjøre negative skritt forhåndsinnhenting. Nesten alle machihnes er raskere for enhetstrinn. Dvs. å endre retningen på arrayet slik at du skanner fra lav til høy i stedet for høy til lav er nesten alltid bedre. Deretter skriver du om litt - vær så snill å forkorte variabelenavnene for å gjøre det lettere å skrive: Forresten vil jeg begynne å bruke shorthands p for pris og s for utjevning, for å lagre skrive. Jeg er lat. men det er sannsynligvis raskere å gjøre. Latensen mellom avgi og avgi-2 er da 1 multipliser og et tillegg, i stedet for en subtrahering og en multiplikasjon mellom avgi og avgi-1. Dvs. mer enn dobbelt så fort. Generelt vil du skrive om gjentakelsen slik at avgi beregnes når det gjelder avgj for j så langt tilbake som mulig, uten å fylle opp maskinen, enten kjøringsenheter eller registre. Du gjør i utgangspunktet flere multiplikasjoner generelt, for å få færre kjeder av multipler (og subtraherer) på den kritiske banen. Det er enkelt å hoppe fra avgi-2 til avgi, du kan sannsynligvis gjøre tre og fire. Nøyaktig hvor langt avhenger av hva maskinen din er, og hvor mange registrerer du har. Og latensen av flytpunktet adder og multiplikator. Eller enda bedre, smaken av kombinert multipliser-tilleggs instruksjon du har - alle moderne maskiner har dem. F. eks Hvis MADD eller MSUB er 7 sykluser lenge, kan du gjøre opptil 6 andre beregninger i skyggen, selv om du bare har en enkelt flytpunktsenhet. Helt pipelined. Og så videre. Mindre hvis pipelined hver andre syklus, som vanlig for dobbel presisjon på eldre chips og GPUer. Samlingskoden skal være programvare pipelined slik at forskjellige loop iterasjoner overlapper. En god kompilator bør gjøre det for deg, men du må kanskje omskrive C-koden for å få best mulig ytelse. Forresten: Jeg mener ikke å foreslå at du skal lage en rekke avg. I stedet vil du trenge to gjennomsnitt hvis avgi er beregnet i form av avgi-2, og så videre. Du kan bruke en rekke avgi hvis du vil, men jeg tror at du bare trenger å ha 2 eller 4 avgs, kalt, kreativt, avg0 og avg1 (2, 3.), og roter dem. Denne typen trick, splitting en akkumulator eller gjennomsnitt i to eller flere, kombinere flere stadier av gjentakelsen, er vanlig i høy ytelse kode. Å, ja: forutregnet ss, etc. Hvis jeg har gjort det riktig, ville dette være identisk i uendelig nøyaktighet. (Dobbeltkikk meg, vær så snill.) Men i finite presisjon FP kan resultatene dine variere, forhåpentligvis bare litt, på grunn av forskjellige avrundinger. Hvis rullingen er riktig og svarene er vesentlig forskjellige, har du sannsynligvis en numerisk ustabil algoritme. Du er den som vilyld vet. Merk: Flytende punktrundefeil vil endre de lave bitene i svaret ditt. Begge på grunn av omarrangering av koden, og bruk av MADD. Jeg tror det er sannsynligvis greit, men du må bestemme. Merk: beregningene for avgi og avgi-1 er nå uavhengige. Så du kan bruke et SIMD instruksjonssett, som Intel SSE2, som tillater operasjon på to 64 bitverdier i et 128 bit bredt register om gangen. Det vil være bra for nesten 2X, på en maskin som har nok ALUer. Hvis du har nok register til å omskrive avgi når det gjelder avgi-4 (og jeg er sikker på at du gjør det på iA64), kan du gå 4X bred hvis du har tilgang til en maskin som 256 bit AVX. På en GPU. Du kan gå for dypere gjentakelser, rewriting avgi i form av avgi-8, og så videre. Noen GPUer har instruksjoner som beregner AXB eller AXBY som en enkelt instruksjon. Selv om det er mer vanlig for 32 bit enn for 64 bit presisjon. På et tidspunkt vil jeg sannsynligvis begynne å spørre: vil du gjøre dette på flere priser om gangen Ikke bare hjelper dette deg med multithreading, det vil også passe det til å kjøre på en GPU. Og med bred SIMD. Mindre sen tillegg Jeg er litt pinlig for ikke å ha brukt Horners Rule til uttrykk som litt mer effektiv. litt forskjellige resultater med avrunding. I mitt forsvar bør enhver anstendig kompilator gjøre dette for deg. Men Hrners regel gjør avhengighetskjeden dypere når det gjelder multiplikasjoner. Du må kanskje unroll og pipelined løkken noen flere ganger. Eller du kan gjøre hvor du forhåndskalkulerer Jeg vet at dette er mulig med boost per: Men jeg vil virkelig unngå å bruke boost. Jeg har googled og ikke funnet noen egnede eller lesbare eksempler. I utgangspunktet vil jeg spore det bevegelige gjennomsnittet av en pågående strøm av en strøm av flytende punktnumre ved å bruke de siste 1000 tallene som en dataprøve. Hva er den enkleste måten å oppnå dette på, jeg eksperimenterte med å bruke et sirkulært array, eksponentielt glidende gjennomsnitt og et enklere glidende gjennomsnitt og fant ut at resultatene fra det sirkulære arrayet passer mine behov best. spurte 12. juni kl 12:38 Hvis dine behov er enkle, kan du bare prøve å bruke et eksponentielt glidende gjennomsnitt. Enkelt sagt, du lager en akkumulatorvariabel, og når koden ser på hver prøve, oppdaterer koden akkumulatoren med den nye verdien. Du velger en konstant alfa som er mellom 0 og 1, og beregner dette: Du trenger bare å finne en verdi av alfa hvor effekten av en gitt prøve bare varer i ca 1000 prøver. Hmm, jeg er egentlig ikke sikker på at dette passer for deg, nå som jeg har sagt det her. Problemet er at 1000 er et ganske langt vindu for et eksponentielt glidende gjennomsnitt. Jeg er ikke sikker på at det finnes en alfa som vil spre gjennomsnittet over de siste 1000 tallene, uten understrøm i flytpunktsberegningen. Men hvis du vil ha et mindre gjennomsnitt, som 30 tall eller så, er dette en veldig enkel og rask måte å gjøre det på. svarte 12. juni kl 12:44 1 på ditt innlegg. Det eksponentielle glidende gjennomsnittet kan la alfa variere. Så dette tillater det å bli brukt til å beregne tidsbasen gjennomsnitt (for eksempel bytes per sekund). Hvis tiden siden den siste akkumulatoroppdateringen er mer enn 1 sekund, lar du alfa være 1,0. Ellers kan du la alpha være (usecs siden sist oppdatering1000000). ndash jxh Jun 12 12 at 6:21 I utgangspunktet vil jeg spore det bevegelige gjennomsnittet av en pågående strøm av en strøm av flytende punktnumre ved å bruke de siste 1000 tallene som en datasample. Vær oppmerksom på at under oppdateringer summen som elementer som addreplaced, unngå kostbare O (N) traversal å beregne summen som trengs for gjennomsnittet - on demand. Totalt er det laget en annen parameter fra T for å støtte f. eks. bruker en lang lang når totalt 1000 lang s, en int for char s, eller en dobbel til total float s. Dette er litt feil i at numsamples kan gå forbi INTMAX - hvis du bryr deg om at du kan bruke en usignert lang lang. eller bruk et ekstra bool data medlem til å registrere når beholderen først fylles mens sykkel nummeprøver rundt arrayet (best deretter omdøpt noe uskyldig som pos). besvart 12. juni 12 klokka 5:19 en antar at kvote-operatør (T-prøve) kvot er faktisk quotvoid operatorltlt (T-prøve) sitat. ndash oPless 8 Jun 14 kl 11:52 oPless ahhh. godt observert. egentlig mente jeg at det skulle være tomt operatør () (T-prøve), men selvfølgelig kunne du bruke hvilken som helst notasjon du likte. Vil fikse, takk. ndash Tony D Jun 8 14 at 14:27Is det mulig å implementere et bevegelige gjennomsnitt i C uten behov for et vindu med prøver Ive fant at jeg kan optimalisere litt, ved å velge et vindu størrelse som er en kraft på to for å tillate litt - skifting i stedet for å dele, men ikke trenger en buffer ville være fint. Er det en måte å uttrykke et nytt glidende gjennomsnittsresultat bare som en funksjon av det gamle resultatet og den nye prøven. Definer et eksempel glidende gjennomsnitt, over et vindu på 4 prøver å være: Legg til ny prøve e: Et glidende gjennomsnitt kan implementeres rekursivt , men for en nøyaktig beregning av det bevegelige gjennomsnittet må du huske den eldste innsatsprøven i summen (dvs. a i eksempelet ditt). For et lengde N bevegelige gjennomsnitt beregner du: hvor yn er utgangssignalet og xn er inngangssignalet. Eq. (1) kan skrives rekursivt som Så du må alltid huske prøven xn-N for å beregne (2). Som påpekt av Conrad Turner, kan du bruke et (uendelig langt) eksponensielt vindu i stedet, som gjør det mulig å beregne utgangen bare fra tidligere utgang og gjeldende inngang: men dette er ikke et standard (uvevet) glidende gjennomsnitt, men eksponentielt vektet glidende gjennomsnitt, hvor prøver tidligere i det siste får en mindre vekt, men (i det minste i teorien) glemmer du aldri noe (vektene blir bare mindre og mindre for prøver langt i det siste). Jeg implementerte et glidende gjennomsnitt uten individuelt elementminne for et GPS-sporingsprogram jeg skrev. Jeg starter med 1 prøve og deler med 1 for å få dagens avg. Jeg legger til en prøve og deler med 2 til den nåværende avg. Dette fortsetter til jeg kommer til lengden av gjennomsnittet. Hver gang etterpå legger jeg til den nye prøven, får gjennomsnittet og fjerner det gjennomsnittet fra totalen. Jeg er ikke en matematiker, men dette virket som en god måte å gjøre det på. Jeg skjønte at det ville slå magen til en ekte matte fyr, men det viser seg at det er en av de aksepterte måtene å gjøre det på. Og det fungerer bra. Bare husk at jo høyere lengden jo tregere følger det du vil følge. Det kan ikke være noe som helst mesteparten av tiden, men når du følger satellitter, hvis du er treg, kan stien være langt fra den faktiske posisjonen, og det vil se dårlig ut. Du kan ha et mellomrom mellom lørdager og de etterfølgende prikkene. Jeg valgte en lengde på 15 oppdatert 6 ganger i minuttet for å få tilstrekkelig utjevning og ikke komme for langt fra den faktiske lette stillingen med glattestrekpunktene. besvart 16 nov 16 kl 23:03 initialiser totalt 0, count0 (hver gang vi ser en ny verdi) En innskriving (scanf), en legger til totalnewValue, ett inkrement (telle), en del av gjennomsnitt (totalt antall) Dette ville være et bevegelige gjennomsnitt over alle innganger For å beregne gjennomsnittet over bare de siste 4 inngangene, ville det kreve 4 inputvariables, kanskje kopiering av hvert inngang til en eldre inputvariable, og deretter beregning av det nye glidende gjennomsnittet. Som summen av de 4 inngangsvariablene delt på 4 (høyre skift 2 ville være bra hvis alle inngangene var positive for å gjøre gjennomsnittlig beregning besvart 3. februar klokken 4:06 som faktisk vil beregne gjennomsnittet og IKKE det bevegelige gjennomsnittet. Etter hvert som tellingen blir større, blir virkningen av en ny inngangsprøve forsvunnet liten ndash Hilmar Feb 3 15 kl 13:53 Ditt svar 2017 Stack Exchange, Inc Jeg er i ferd med å skape en forex trading algoritme og ønsket å prøve mitt skudd ved å beregne EMA (eksponentielle Moving Averages). Mine resultater ser ut til å være riktige (sammenlignet med beregningen ns jeg gjorde for hånd) så jeg tror at følgende metode fungerer, men ville bare få et ekstra sett med øyne for å sikre at jeg ikke savner noe. Merk at dette bare returnerer EMA for den siste prisen, det returnerer ikke en rekke EMAer som det er ikke det jeg trenger for søknaden min. Rekursjon er et godt verktøy for riktig jobb, men her er det vant til å utføre enkel looping. Som sådan koden. er vanskeligere å lese og begrunnelse om. er langsommere fordi mye av koden i ema bare trenger å kjøre en gang. vil mislykkes med stor nok verdi av vinduet på grunn av overfylt Pythons call stack. Vennligst dokument minst parametere for hver funksjon, f. eks. Dette vinduet er lengden på vinduet, og den posisjonen teller bakover fra datasendingen. (Faktisk ville det være tydeligere hvis posisjonen var en normal fremoverindeks i data) Løft et unntak når du finner en parameter har en ugyldig verdi. Returnerer ingen i stedet vil bare føre til et mer forvirrende unntak senere. Faktisk, hvis jeg prøver Indikatorer (). Ema (closeprices, 600) får jeg uendelig rekursjon fordi sma returnerer None. som gjør ema call sma igjen og igjen. Det forrige punktet viser også at hvis len (data) lt vindu 2 ikke er riktig gyldighetskontroll. Den 1 i data-vinduet2 1: - vindu 1 virker ikke riktig for meg. Jeg antar at du vil ha data-window2: - window Oppsigelsen returner tidligereem er på et merkelig sted fordi du på dette tidspunktet har beregnet et nytt aktuelt emne. Dette er grunnleggende tilfelle av rekursjonen, og det er vanlig å håndtere basissettet først. Mitt forslag til ema: svarte 26. november kl 14:56 Ganske grunne gjennomgang: Du trenger ikke å skrive en klasse for hva du gjør (og jeg foreslår at du ser på denne videoen). Klassen din innkapsler ikke noen data, og du bruker den bare til å ha dine funksjoner i samme enhet. Jeg antar at ting ville være lettere å forstå hvis du skulle definere klassemetode for å gjøre det klart at du ikke vil stole på noe som helst tilfelle. Men et enda bedre alternativ ville være å bare definere funksjoner i en indikatormodul. svarte 24. november kl 14:04 Takk for forslagene jeg faktisk hadde dem som classmethods og debatterte å gå frem og tilbake mellom selv å bruke en klasse eller bare definere funksjoner i en indikatormodul (som jeg nå skal gjøre). ndash ChrisC Nov 25 14 at 19:12 Bare så på videoen, gode ting. ndash ChrisC Nov 25 14 kl 19:43 Ditt svar 2017 Stack Exchange, Inc

Comments