Exponencial moving average c code


Eu perfilei isso usando o perfil do Visual C, e isso representa cerca de 35 do tempo de execução. Essa média móvel exponencial é chamada mais do que um trilhão de vezes, porque é usada repetidamente no processamento de mais de 400 gigabytes de dados. Os dados estão saindo de uma matriz de disco de estado sólido Raid Level 0, portanto, lê as contas de dados por menos de 5 do tempo. O tamanho do preço é de cerca de 100. Eu, originalmente, acelerado por um fator de 4, precalculando a maior parte dos dados possível. Então eu pude aumentá-lo novamente por um fator de ndash PaeneInsula 30 de outubro 11 às 20:41 Eu consegui aumentar a velocidade novamente por um fator de 12 por multithreading (a natureza dos dados é tal que pode ser multithreaded em De tal forma que a carga está perfeitamente equilibrada.) E eu funciono em um i7 990x (que tem 6 núcleos, hipertensos de um total de 12), overclocked. Ndash PaeneInsula 30 de outubro 11 às 20:51 Claro, multithreading pode ajudar. Mas você quase certamente pode melhorar o desempenho em uma única máquina roscada. Primeiro, você está calculando isso na direção errada. Somente as máquinas mais modernas podem fazer pré-busca de strings negativos. Quase todos os machihnes são mais rápidos para os passos da unidade. Isto é, Mudar a direção da matriz para que você digitalize de baixo a alto, em vez de alto a baixo, é quase sempre melhor. Em seguida, reescrevendo um pouco - permita-me encurtar os nomes das variáveis ​​para facilitar o tipo: Por sinal, vou começar a usar shorthands p por preço e s para suavizar, para salvar a digitação. Sou preguiçosa. Mas provavelmente é mais rápido. A latência entre avgi e avgi-2 é então 1 multiplicar e adicionar, em vez de subtrair e multiplicar entre avgi e avgi-1. Isto é, Mais do que duas vezes mais rápido. Em geral, você deseja reescrever a recorrência para que o avgi seja calculado em termos de avgj para j, tanto quanto possível, sem preencher a máquina, unidades de execução ou registradores. Você basicamente faz mais multiplicações em geral, para obter menos cadeias de múltiplos (e subtrai) no caminho crítico. Saltar de avgi-2 para avgi é fácil, você provavelmente pode fazer três e quatro. Exatamente em que medida depende do que é a sua máquina e de quantos registros você possui. E a latência do sumador e multiplicador de ponto flutuante. Ou, melhor ainda, o sabor das instruções de multiplicação múltiplas combinadas que você tem - todas as máquinas modernas as possuem. Por exemplo. Se o MADD ou o MSUB tiverem 7 ciclos de duração, você pode fazer até 6 outros cálculos na sua sombra, mesmo se você tiver apenas uma única unidade de ponto flutuante. Totalmente pipelined. E assim por diante. Menos se pipelined em todos os outros ciclos, como é comum para a dupla precisão em chips anteriores e GPUs. O código de montagem deve ser o software pipelined para que diferentes iterações de loop se sobrepõem. Um bom compilador deve fazer isso para você, mas talvez seja necessário reescrever o código C para obter o melhor desempenho. By the way: NÃO QUERO sugerir que você esteja criando uma série de valores médios. Em vez disso, você precisaria de duas médias se avgi for calculado em termos de avgi-2, e assim por diante. Você pode usar uma série de avgi se quiser, mas acho que você só precisa ter 2 ou 4 avgs, chamado, criativamente, avg0 e avg1 (2, 3.), e gire-os. Este tipo de truque, dividindo um acumulador ou média em dois ou mais, combinando múltiplos estágios da recorrência, é comum no código de alto desempenho. Oh, sim: precalcular ss, etc. Se eu fiz isso direito, em uma precisão infinita isso seria idêntico. (Verifique-me, por favor.) No entanto, em precisão finita FP, seus resultados podem diferir, espero que apenas um pouco, devido a diferentes arredondamentos. Se o desenrolar estiver correto e as respostas forem significativamente diferentes, você provavelmente possui um algoritmo numericamente instável. Você é quem sabe. Nota: os erros de arredondamento de ponto flutuante mudarão os bits baixos da sua resposta. Ambos por reorganizar o código e usar o MADD. Eu acho que provavelmente está bem, mas você tem que decidir. Nota: os cálculos para avgi e avgi-1 agora são independentes. Então você pode usar um conjunto de instruções SIMD, como Intel SSE2, que permite a operação em dois valores de 64 bits em um registro de 128 bit de largura de cada vez. Isso será bom para quase 2X, em uma máquina que tenha ALUs suficientes. Se você tiver registros suficientes para reescrever avgi em termos de avgi-4 (e tenho certeza que você faz no iA64), então você pode ir 4X de largura, se você tiver acesso a uma máquina como AVX de 256 bits. Num GPU. Você pode recorrer a recorrências mais profundas, reescrever avgi em termos de avgi-8, e assim por diante. Algumas GPUs têm instruções que calculam AXB ou mesmo AXBY como uma única instrução. Embora isso seja mais comum para 32 bits do que para precisão de 64 bits. Em algum momento, eu provavelmente começaria a perguntar: você quer fazer isso em vários preços por vez. Nem isso isso ajuda você a multithreading, ele também irá se adequar a isso em uma GPU. E usando o SIMD largo. Adição tardia menor Estou um pouco envergonhada por não ter aplicado a regra Horners para expressões como um pouco mais eficiente. Resultados ligeiramente diferentes com o arredondamento. Na minha defesa, qualquer compilador decente deve fazer isso por você. Mas a regra de Hrners torna a cadeia de dependência mais profunda em termos de multiplica. Você pode precisar desenrolar e pipelined o loop algumas vezes mais. Ou você pode fazer onde você precalcula. Eu sei que isso é viável com o aumento de acordo com: Mas eu realmente gostaria de evitar o uso de impulso. Eu mencionei e não encontrei nenhum exemplo adequado ou legível. Basicamente eu quero acompanhar a média móvel de um fluxo contínuo de um fluxo de números de ponto flutuante usando os 1000 números mais recentes como amostra de dados. Qual é a maneira mais fácil de alcançar isso, experimentei usar uma matriz circular, uma média móvel exponencial e uma média móvel mais simples e descobriu que os resultados da matriz circular adequavam minhas necessidades. 12 de junho 12 às 4:38 Se suas necessidades são simples, você pode tentar usar uma média móvel exponencial. Simplificando, você faz uma variável de acumulador e, à medida que seu código examina cada amostra, o código atualiza o acumulador com o novo valor. Você escolhe um alfa constante que está entre 0 e 1 e calcula isso: você precisa apenas encontrar um valor de alfa onde o efeito de uma determinada amostra dura apenas cerca de 1000 amostras. Hmm, na verdade, não tenho certeza de que isso é adequado para você, agora que eu já coloquei aqui. O problema é que 1000 é uma janela bastante longa para uma média móvel exponencial. Não tenho certeza se houver um alfa que espalhe a média nos últimos 1000 números, sem fluxo inferior no cálculo do ponto flutuante. Mas se você quisesse uma média menor, como 30 números ou mais, esta é uma maneira muito fácil e rápida de fazê-lo. Respondeu 12 de junho 12 às 4:44 1 na sua postagem. A média móvel exponencial pode permitir que o alfa seja variável. Assim, isso permite que ele seja usado para calcular médias base de tempo (por exemplo, bytes por segundo). Se o tempo desde a última atualização do acumulador for superior a 1 segundo, você deixa alfa ser 1.0. Caso contrário, você pode deixar alpha be (usecs desde a última atualização1000000). Ndash jxh 12 de junho 12 às 6:21 Basicamente eu quero acompanhar a média móvel de um fluxo contínuo de um fluxo de números de ponto flutuante usando os 1000 números mais recentes como uma amostra de dados. Observe que as atualizações abaixo atualizam o total como elementos como adicionados, evitando a trajetória O (N) cara para calcular a soma - necessária para a média - na demanda. Total é feito um parâmetro diferente de T para suportar, e. Usando um longo tempo quando totalizando 1000 long s, um int para char s, ou um duplo para float total s. Isso é um pouco falho em que numsamples poderia ultrapassar o INTMAX - se você se importar, você poderia usar um sinal não assinado por muito tempo. Ou use um membro extra de dados do bool para gravar quando o recipiente é preenchido pela primeira vez ao andar de bicicleta numsamples em torno da matriz (melhor então renomeado algo inócuo como pos). Respondeu 12 de junho 12 às 5:19 um assume que quotvoid operator (T sample) quot é realmente quotvoid operatorltlt (T sample) quot. Ndash oPless Jun 8 14 às 11:52 oPless ahhh. Bem manchado. Na verdade, eu quis dizer que ele seria um operador vazio () (amostra T), mas é claro que você poderia usar qualquer notação que você gostasse. Vou consertar, obrigado. Ndash Tony D 8 de junho 14 às 14: 27 É possível implementar uma média móvel em C sem a necessidade de uma janela de amostras Achei que posso otimizar um pouco, escolhendo um tamanho de janela que é um poder de dois para permitir bit - Desligar em vez de dividir, mas não precisar de um buffer seria bom. Existe uma maneira de expressar um novo resultado de média móvel apenas como função do resultado antigo e da nova amostra. Definir um exemplo de média móvel, em uma janela de 4 amostras para ser: Adicionar nova amostra e: Uma média móvel pode ser implementada de forma recursiva , Mas para uma computação exata da média móvel você deve lembrar a amostra de entrada mais antiga na soma (ou seja, a no seu exemplo). Para um comprimento N média móvel você calcula: onde yn é o sinal de saída e xn é o sinal de entrada. Eq. (1) pode ser escrito de forma recursiva, então você sempre precisa se lembrar da amostra xn-N para calcular (2). Conforme demonstrado por Conrad Turner, você pode usar uma janela exponencial (infinitamente longa) em vez disso, o que permite calcular a saída apenas da saída passada e da entrada atual: mas esta não é uma média móvel padrão (não ponderada), mas exponencialmente Média móvel ponderada, onde as amostras no passado obtêm um peso menor, mas (pelo menos em teoria) você nunca esquece nada (os pesos ficam cada vez menores e menores para amostras no passado). Eu implementei uma média móvel sem memória de item individual para um programa de rastreamento GPS que eu escrevi. Eu começo com 1 amostra e divide por 1 para obter o valor médio atual. Em seguida, adicione uma amostra e divida em 2 para a média atual. Isso continua até chegar ao comprimento da média. Cada vez, adiciono na nova amostra, obtenho a média e retire essa média do total. Eu não sou matemático, mas isso pareceu uma boa maneira de fazê-lo. Eu pensei que isso tornaria o estômago de um verdadeiro matemático, mas, parece que é uma das maneiras aceitas de fazê-lo. E funciona bem. Basta lembrar que, quanto mais alto for seu comprimento, mais lento seguirá o que você deseja seguir. Isso pode não importar a maior parte do tempo, mas ao seguir os satélites, se você estiver lento, a trilha pode estar longe da posição real e parecerá ruim. Você poderia ter uma lacuna entre o Sáb e os pontos de fuga. Eu escolhi um período de 15 atualizado 6 vezes por minuto para obter um alisamento adequado e não chegar muito longe da posição real de SAT com os pontos de trilhos alisados. Respondido 16 de novembro 16 às 23:03 inicializar total 0, count0 (cada vez que vê um novo valor Então uma entrada (scanf), uma adicionar totalnewValue, um incremento (contagem), uma média de divisão (total total) Esta seria uma média móvel em relação a Todas as entradas Para calcular a média sobre apenas as últimas 4 entradas, seria necessário 4 variáveis ​​de entrada, talvez copiando cada entrada para uma variável de entrada mais antiga, calculando a nova média móvel. Como soma das 4 variáveis ​​de entrada, divididas por 4 (o turno direito 2 seria Bom, se todas as entradas fossem positivas para que o cálculo médio fosse respondido 3 de fevereiro 15 às 4:06 Isso realmente calculará a média total e NÃO a média móvel. À medida que a contagem aumenta, o impacto de qualquer nova amostra de entrada se torna ndash extremamente lento Hilmar Feb 3 15 às 13:53 Sua resposta 2017 Stack Exchange, Inc

Comments

Popular posts from this blog

Binary options channel trading

Cta opções negociação

Forex margem significado