Friday, 17 November 2017

Exponential glidande medelvärde c ++


Jag har profilerat detta med hjälp av Visual C-profiler och det står för cirka 35 av speltiden. Det exponentiella glidande medlet kallas mer än en biljon gånger, eftersom det används upprepade gånger vid behandling av mer än 400 gigabyte data. Data kommer från En raidnivå 0 solid state disk array, så att läsa datakonton för mindre än 5 av tiden Prisstorleken är cirka 100 Jag förstegrade uppgiften med en faktor 4 genom att förberäkna så mycket data som möjligt Sedan var jag Kunna öka den igen med en faktor PaeneInsula 30 okt på 20 41. Jag kunde öka hastigheten igen med en faktor 12 genom multithreading det är naturen av data så att den kan multithreaded på så sätt att Lasten är perfekt balanserad Och jag har den igång på en i7 990x som har 6 kärnor, överhettad av totalt 12, överklockade PaeneInsula 30 okt på 20 51. Säker, multithreading kan hjälpa Men du kan nästan säkert förbättra prestanda på en enda Gängad maskin. Först beräknar du det i fel riktning Endast de modernaste maskinerna kan göra negativa steg före förhämtning Nästan alla maskiner är snabbare för enhetssteg Jag ändrar riktningen för matrisen så att du skannar från låg till hög snarare än hög till låg är Nästan alltid bättre. Näste omskrivning lite - snälla tillåta mig att förkorta de variabla namnen för att göra det lättare att skriva. Förresten kommer jag att börja använda shorthands p för pris och s för utjämning, för att spara typing jag m lat. Det är förmodligen snabbare att göra. Latensen mellan avg i och avg i-2 är då 1 multiplicera och en add, snarare än en subtrahering och en multiplicering mellan avg i och avg i-1 I e mer än dubbelt så fort. I allmänhet , Du vill skriva om återkommande så att avg i beräknas i termer av avg j ​​för j så långt tillbaka som möjligt, utan att fylla i maskinen, antingen exekveringsenheter eller register. Du gör i grund och botten mer multipla överlag i ordning Att få färre multipelkedjor och subtrahera den kritiska Väg Hoppar från avg i-2 till avg i är lätt, du kan noga göra tre och fyra Exakt hur långt beror på din maskin, och hur många register du har. Och latens för floating point adder och multiplikator Eller bättre Ändå är smaken av kombinerad multiplikator-instruktion du har - alla moderna maskiner har dem E g om MADD eller MSUB är 7 cykler lång kan du göra upp till 6 andra beräkningar i sin skugga, även om du bara har en enda flytande Punktenhet Full pipelined Och så vidare Mindre om pipelined varje andra cykel, vilket är vanligt för dubbel precision på äldre chips och GPU: er. Sammansättningskoden ska vara mjukvara pipelined så att olika loop-iterationer överlappar. En bra kompilator bör göra det för dig, men du kanske Måste skriva om C-koden för att få bästa möjliga prestanda. Med det sättet betyder det inte att jag borde skapa en uppsättning avg i stället skulle du behöva två medelvärden om avg i beräknas i form av avg i-2, Och så vidare Du kan använda en rad avg jag om du Du vill ha, men jag tror att du bara behöver ha 2 eller 4 avgs, kallade, kreativt, avg0 och avg1 2, 3 och rotera dem. Denna typ av trick, dela upp en ackumulator eller medelvärde i två eller flera, som kombinerar flera steg Av återkommande är vanligt i högprestandakod. Oj, ja, beräkna ss osv. Om jag har gjort det rätt, i oändlig precision, skulle det vara identiskt. Dubbelkoll mig, tack. Men i slutgiltig precision FP kan dina resultat skilja sig, Förhoppningsvis bara lite på grund av olika avrundningar Om avrollningen är korrekt och svaren är väsentligt annorlunda har du förmodligen en numeriskt instabil algoritm. Du är den som villyld know. Note floating point avrundningsfel kommer att ändra de låga bitarna i ditt svar Både för att Om att omarrangera koden och använda MADD Jag tror det är nog okej, men du måste bestämma. Notera beräkningarna för avg i och avg i-1 är nu självständiga Så du kan använda en SIMD instruktion, som Intel SSE2, vilket medger Operation på två 64 Bitvärden i ett 128 bitars brett register i taget Det ska vara bra för nästan 2X på en maskin som har tillräckligt med ALU. Om du har tillräckligt med register för att skriva om avg i när det gäller avg i-4 och jag är säker på att du gör det IA64, då kan du gå 4X bred om du har tillgång till en maskin som 256 bitars AVX. På en GPU kan du gå för djupare återkommande, omskriva avg i när det gäller avg i-8 och så vidare. Vissa GPU har instruktioner Som beräknar AX B eller till och med AX BY som en enskild instruktion Även om det är vanligare för 32 bit än för 64 bitars precision. At någon punkt skulle jag förmodligen börja fråga, vill du göra detta på flera priser i taget Inte bara gör detta Hjälpa dig med multithreading, det kommer också att passa det för att köra på en GPU och använda bred SIMD. Minor Late Addition. I är lite embarassed att inte ha tillämpat Horner s Rule för uttryck som. Lite effektivare lite annorlunda resultat med rounding. In Mitt försvar, någon anständig kompilator borde göra det för dig. Men Hrners regel gör beredskapskedjan Per när det gäller multiplicer Du kanske behöver unroll och pipelines slingan några gånger eller så kan du göra. Därför är du precalculate. I vet att detta är möjligt med boost som per. Men jag vill verkligen undvika att använda boost jag har googled och Hittade inte några lämpliga eller läsbara exempel. I grund och botten vill jag spåra det rörliga genomsnittet av en pågående ström av en ström av flytande punktnummer med de senaste 1000 siffrorna som ett dataprov. Vilket är det enklaste sättet att uppnå detta. Jag experimenterade med Med hjälp av ett cirkulärt array, exponentiellt glidande medelvärde och ett enklare glidande medelvärde och fann att resultaten från den cirkulära gruppen passade mina behov bäst. Skakad 12/12 12 på 4 38. Om dina behov är enkla kan du bara försöka använda en exponentiell rörelse Medan du gör en ackumulatorvariabel, och när din kod tittar på varje prov, uppdaterar koden ackumulatorn med det nya värdet. Du väljer en konstant alfa som är mellan 0 och 1 och beräknar detta. Du behöver bara hitta Ett värde av alf A där effekten av ett givet prov endast varar för cirka 1000 prov. Hmm, jag är inte säker på att det här är lämpligt för dig nu när jag har lagt den här Problemet är att 1000 är ett ganska långt fönster för ett exponentiellt rörligt medelvärde Jag är inte säker på att det finns en alfa som skulle sprida genomsnittet över de senaste 1000 siffrorna, utan underflöde i flytpunktsberäkningen. Men om du ville ha ett mindre medelvärde, som 30 nummer eller så, är det här ett mycket enkelt och snabbt sätt att göra It. answered 12 juni 12 på 4 44. 1 på ditt inlägg Det exponentiella glidande medlet kan tillåta alfabet att vara variabelt Så här gör det att det kan användas för att beräkna tidsbasen medelvärden, t. ex. byte per sekund Om tiden sedan den senaste ackumulatorns uppdatering är mer Än 1 sekund, låter du alpha vara 1 0 Annars kan du låta alfa vara usecs sedan senaste uppdateringen 1000000 jxh Jun 12 12 på 6 21. Basiskt vill jag spåra det rörliga genomsnittet av en pågående ström av en ström med flytande punktnummer med hjälp av De senaste 1000 siffrorna som ett dataprov. Notera t Hade nedan uppdateringar summan som element som tillsatt ersatt, vilket undviker dyrt ON-traversal för att beräkna summan som behövs för genomsnittet-on demand. Total görs en annan parameter från T för att stödja t ex med en lång längd när det sammanlagda 1000 lång s, En int för char s eller en dubbel till total float s. Detta är lite fel i att nummpples kan gå förbi INTMAX - om du bryr dig att du kan använda en unsigned long long eller använda en extra bool data medlem att spela in när behållaren är Först fylld medan cykeldonprover runt arrayen bäst omdöpades till något oskyldigt som pos. answered 12/12 12 på 5 19.one antar att tomrumsoperatör T-provet är faktiskt tomt operatör T-prov oPlöst 8 juni 14 på 11 52. oPless ahhh väl spotted faktiskt Jag menade att det skulle vara tomt operatör T-prov men självklart kan du använda vilken anteckning du vill, kommer att fixa, tack Tony D Jun 8 14 vid 14 27C-algoritmen för exponentialrörelse med nolltidslängd. Last Modified 2012-08-13 . Jag har försökt att genomföra en låg Frekvens cutoff i c som väsentligen tar en ström av siffror och släpper ut utgången som filtrerar ut högfrekventa rörelsejitter, men det är viktigt att de främre viktiga numren anses omedelbart eftersom data är tidskritisk att det är att styra en rörelsesimulationsbas med utgång Från lite spelprogramvara Jag har en arbetsviktad glidande genomsnittlig algoitm men kunde göra med något lite mer responsivt i frontänden, och jag hittade det här. Pseudokoden finns som följer. Inmatningar Pris NumericSeries, Period NumericSimple Variables Faktor 0, lag 0.if CurrentBar 1 börja ZLEMA Prisfaktor 2 Period 1 lag Period-1 2 sluta börja ZLEMA faktor 2 Pris-prislag 1-faktor ZLEMA 1 end. I har översatt den till C och min kod är Som följer. Men det verkar inte som att jag beter sig som jag förväntar mig. Det verkar vara nästan där men ibland får jag ett något lägre värde än alla artiklar i köen när de är alla högre. Min kö och antalet artiklar i Det är Passerade som parametrar, med den senaste som alltid framgår, passerar jag också en inkrementell räknare som börjar vid 0 som krävs av funktionen. Jag är inte säker på att jag har tolkat meningen med ZLEMA 1 korrekt eftersom den inte är klar i Hans pseudokod, så jag antog att detta var det sista samtalet s zlema och jag antar även Pris betyder faktiskt Pris 0 Kanske har jag det här fel. Jag skulle kopiera de faktiska zlemaberäknade värdena tillbaka till min ursprungliga kö innan Nästa samtal Jag byter inte den ursprungliga köen på alla andra än att bara flytta alla värden ett till slutet och sätta in det senaste i början Koden som jag använder för att göra detta är. Vara extremt tacksam om någon med bättre förståelse för matematiken Kan du snälla se till att jag ser det här för att se om jag har någonting något fel. Tack så mycket i förväg om du kan hjälpa. Först och främst tack för allting, mycket uppskattat. Det är vettigt att jag antar, så jag antar då det bästa jag Kan hoppas på är helt enkelt en exponenti Al glidande medelvärde, accepterar det att det kommer att finnas en liten fördröjning men detta kommer att minimeras av tyngre frontvikt än vad som anges i typviktat glidande medelvärde. Jag har även denna algoritm men ett liknande problem med att värdena inte verkar rätt korrekta om inte detta Är naturen av formeln. Till exempel, säg att mitt sortiment innehåller 16 värden, alla 0 4775 - utgången är 0 4983, men jag förväntar mig att den ska vara 0 4775.Jag ser det här rätt ut. Exponentiell Flytande Genomsnittlig Float Ema Float Vals, Int NumVals, Int CurrentSample Statisk Float Faktor 0 Statisk Float Lastema 0 Float Ema. if CurrentSample 1 EmaVals 0 Faktor 2 0 Float NumVals 1 0 Andra Ema FactorVals 0 1 0 - Factor Lastema Lastema Ema. Returnera ema Omvänt är utsignalen ibland lägre än var och en av ingångarna, även om alla är högre. Den kallas på samma sätt som zlema ovan, med en inkrementell räknare. Formeln och pseudokoden för den här är här - Tack Igen, ber om ursäkt för mitt missförstånd om några av grunderna Vänliga hälsningar, Chris J. As för koden jag skrev upp, har du rätt om matrisstorleken. Det borde vara enkelt att fixa. För dina frågor.1 Filterkonstanten representerar en frekvensavbrott Jag använde en Digital Signal Processing DSP för den här tekniken. Ki Low-pass sfilter är en enkel förklaring. Du vill ha sektionen för diskret tid. I mitt fall är A den RC-Constant som de talar om. Så den frekvens som den skär ut är över 1 2 pi A Om du inte har en förståelse för frekvensdomänteori kan detta bli komplicerat. I ditt fall Ju högre du gör A desto lägre frekvens kommer det här filtret att tillåta, vilket betyder att det kommer att släta ut kurvan mer Och mer Ju lägre du gör det desto mer buller tillåts i systemet. Kom ihåg att A måste vara större än eller lika med 1 för att vara effektiv. Jag satt tillbaka XLS igen, den här gången utan att ändra randnummer. Justera A-konstanten och titta på Hur det släpper ut eller filtrerar bort högfrekvensvariationerna.2 Den sista punkten i ingångsargumentet har det senaste värdet.3 Samma gäller för utmatningsraden Den sista är det senaste värdet.5 NUMVALS är godtyckligt Du kan kontinuerligt Lägg till i inmatnings - och utmatningsfältet så många gånger du vill och det skulle inte påverka filtret. I synnerhet använde jag 49 poäng Men jag kan enkelt ta bort de senaste 20 och de första 29 utgångarna skulle förbli densamma Funktionen är inte Baserat på hur många poäng som används. Jag skulle vilja För att nämna att jag utvecklade denna funktion för en engångsomvandling Om du ville göra en omvandling till nästa värde i flygningen kunde du försöka något enklare som bifogat igen jag är rostig på c Jag hoppas att det här är rätt Det enda du skulle ha Behöver leverera är ingången och filtret konstant. Låt mig veta om detta hjälper.

No comments:

Post a Comment