Monday 12 March 2018

Moving average array c ++


Estou tentando calcular a média móvel de um sinal. O valor do sinal (um duplo) é atualizado em horários aleatórios. Estou procurando uma maneira eficiente de calcular sua média ponderada no tempo ao longo de uma janela de tempo, em tempo real. Eu poderia fazê-lo sozinho, mas é mais desafiante do que eu pensava. A maioria dos recursos que eu encontrei pela internet calculam a média móvel do sinal periódico, mas as atualizações das minas em tempo aleatório. Alguém conhece bons recursos para isso. O truque é o seguinte: você obtém atualizações em horários aleatórios através da atualização vazia (tempo int, valor flutuante). No entanto, você também precisa acompanhar quando uma atualização cai fora da janela de tempo, então você define um alarme chamado no momento N, que remove a atualização anterior de ser novamente considerado novamente na computação. Se isso acontecer em tempo real, você pode solicitar que o sistema operacional faça uma chamada para um método void dropoffoldestupdate (int time) para ser chamado no tempo N Se esta é uma simulação, você não pode obter ajuda do sistema operacional e você precisa Faça isso manualmente. Em uma simulação, você chamaria métodos com o tempo fornecido como um argumento (que não se correlaciona com o tempo real). No entanto, uma suposição razoável é que as chamadas são garantidas de tal forma que os argumentos de tempo estão aumentando. Neste caso, você precisa manter uma lista ordenada de valores do tempo de alarme e, para cada atualização e leitura, você verifica se o argumento de tempo é maior do que a cabeça da lista de alarmes. Embora seja maior, você faz o processamento relacionado ao alarme (abandone a atualização mais antiga), remova a cabeça e verifique novamente até que todos os alarmes anteriores ao tempo fornecido sejam processados. Em seguida, faça a chamada de atualização. Tenho até agora assumido que é óbvio o que você faria para a computação real, mas vou elaborar apenas no caso. Eu suponho que você tenha um método flutuante lido (int time) que você usa para ler os valores. O objetivo é tornar este chamado tão eficiente quanto possível. Então você não calcula a média móvel sempre que o método de leitura é chamado. Em vez disso, você precomputa o valor a partir da última atualização ou o último alarme, e ajuste esse valor por algumas operações de ponto flutuante para explicar a passagem do tempo desde a última atualização. (I. E. Um número constante de operações, exceto para talvez processar uma lista de alarmes empilhados). Esperemos que isso seja claro - este deve ser um algoritmo bastante simples e bastante eficiente. Otimização adicional. Um dos problemas restantes é se uma grande quantidade de atualizações acontecer dentro da janela de tempo, então há muito tempo para o qual não há leituras nem atualizações e, em seguida, uma leitura ou atualização vem junto. Nesse caso, o algoritmo acima será ineficiente para atualizar de forma incremental o valor de cada uma das atualizações que está caindo. Isso não é necessário porque nos preocupamos apenas com a última atualização além da janela de tempo, então, se houver uma maneira de descartar as atualizações mais antigas, isso ajudaria. Para fazer isso, podemos modificar o algoritmo para fazer uma busca binária de atualizações para encontrar a atualização mais recente antes da janela de tempo. Se houver relativamente poucas atualizações que precisam ser descartadas, pode-se incrementar o valor para cada atualização descartada. Mas se houver muitas atualizações que precisam ser descartadas, pode-se recalcular o valor a partir do zero depois de deixar as atualizações antigas. Apêndice sobre Computação Incremental: Devo esclarecer o que quero dizer com a computação incremental acima na frase ajustar esse valor por um par de operações de ponto flutuante para explicar a passagem do tempo desde a última atualização. Computação inicial não incremental: então iterar sobre os atuais relevantes em ordem crescente de tempo: tempo de exibição de motionaverage (sum tempo de atualização). Agora, se exatamente uma atualização cai fora da janela, mas nenhuma nova atualização chegou, ajuste a soma como: (note que é priorupdate que tem o timestamp modificado para iniciar o início da última janela). E se exatamente uma atualização entrar na janela, mas nenhuma nova atualização cai, ajuste a soma como: Como deve ser óbvio, este é um esboço áspero, mas espero que mostre como você pode manter a média de que é O (1) operações por atualização Em uma base amortizada. Mas observe uma otimização adicional no parágrafo anterior. Observe também as questões de estabilidade aludidas em uma resposta mais antiga, o que significa que os erros de ponto flutuante podem se acumulam em um grande número de tais operações incrementais, de modo que existe uma divergência com o resultado da computação total que é significativa para o aplicativo. Se uma aproximação é OK e há um tempo mínimo entre amostras, você pode tentar super-amostragem. Tenha uma matriz que represente intervalos de tempo uniformemente espaçados que sejam menores do que o mínimo, e em cada período de tempo armazene a última amostra que foi recebida. Quanto menor for o intervalo, mais próxima será a média para o valor verdadeiro. O período não deve ser superior a metade do mínimo ou há uma chance de perder uma amostra. Respondido 15 de dezembro às 18:12 respondido 15 de dezembro às 22:38 Obrigado pela resposta. Uma melhoria que seria necessário para realmente quotcachequot o valor da média total, então nós não vamos fazer o loop o tempo todo. Além disso, pode ser um ponto menor, mas não seria mais eficiente usar um deque ou uma lista para armazenar o valor, já que assumimos que a atualização virá na ordem correta. A inserção seria mais rápida do que no mapa. Ndash Arthur 16 de dezembro 11 às 8:55 Sim, você pode armazenar em cache o valor da soma. Subtrair os valores das amostras que você apaga, adicione os valores das amostras que você inseriu. Além disso, sim, um dequeltpairltSample, Dategtgt pode ser mais eficiente. Eu escolhi o mapa para legibilidade e a facilidade de invocar o mapa :: upperbound. Como sempre, escreva primeiro o código correto, depois perfile e mude as mudanças incrementais. Ndash Rob Dec 16 11 at 15:00 Nota: Aparentemente, esta não é a maneira de abordar isso. Deixando-o aqui para referência sobre o que há de errado com essa abordagem. Verifique os comentários. ATUALIZADO - com base no comentário Olis. Não tenho certeza sobre a instabilidade de que ele está falando. Use um mapa ordenado dos tempos de chegada contra valores. Após a chegada de um valor, adicione a hora de chegada ao mapa ordenado juntamente com seu valor e atualize a média móvel. Advertindo isso é pseudo-código: lá. Não totalmente elaborado, mas você consegue a ideia. Coisas a serem observadas. Como eu disse, o acima é pseudo-código. Você precisará escolher um mapa apropriado. Não remova os pares à medida que você itera, pois você invalidará o iterador e terá que começar de novo. Veja o comentário Olis abaixo também. Respondeu 15 de dezembro às 12:22 Isso não funciona: ele não leva em consideração a proporção do comprimento da janela para cada valor. Além disso, essa abordagem de adicionar e depois subtrair é apenas estável para tipos inteiros, não flutuadores. Ndash Oliver Charlesworth 15 de dezembro às 12:29 OliCharlesworth - desculpe, perdi alguns pontos-chave na descrição (dupla e ponderada no tempo). Vou atualizar. Obrigado. Ndash Dennis 15 de dezembro às 12:33 O tempo de ponderação é mais um problema. Mas isso não é o que eu estou falando. Eu estava me referindo ao fato de que quando um novo valor primeiro entra na janela de tempo, sua contribuição para a média é mínima. Sua contribuição continua a aumentar até um novo valor entrar. Ndash Oliver Charlesworth 15 de dezembro 11 às 12: 35 Eu sei que isso é realizável com o impulso 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 números 1000 mais recentes como uma amostra de dados. Qual é a maneira mais fácil de conseguir 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 correspondiam melhor às 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, conforme 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ê só precisa encontrar um valor de alfa onde o efeito de uma determinada amostra dura apenas cerca de 1000 amostras. Hmmm, na verdade, não tenho certeza de que isso é adequado para você, agora que eu 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. Então isso permite que ele seja usado para calcular médias base de tempo (por exemplo, bytes por segundo). Se o tempo decorrido desde a última atualização do acumulador for superior a 1 segundo, você deixa alfa ser 1.0. Caso contrário, você pode deixar o alfa ser (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 amostra de dados. Observe que as atualizações abaixo atualizam o total como elementos como adicionados substituídos, evitando a passagem O (N) dispendiosa para calcular a soma - necessária para a demanda média. 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 adicional de dados do bool para gravar quando o recipiente é preenchido pela primeira vez ao andar de bicicleta numsamples em torno da matriz (o melhor que renomeou 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 visto. 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 Arredondamento simples (média móvel) em C Como diagnóstico, quero exibir o número de ciclos por segundo no meu aplicativo. (Pense quadros por segundo em um atirador em primeira pessoa.) Mas eu não quero exibir o valor mais recente, ou a média desde o lançamento. O que eu quero calcular é a média dos últimos valores X. Minha pergunta é, suponho, sobre a melhor maneira de armazenar esses valores. Meu primeiro pensamento foi criar uma matriz de tamanho fixo, então cada valor novo iria empurrar o mais antigo. Esta é a melhor maneira de fazê-lo Se assim for, como eu iria implementá-lo EDITAR: Heres a classe que eu escrevi: RRQueue. Ele herda a fila, mas impõe a capacidade e descida, se necessário. Relacionado a. Conjunto simples de round robin (média móvel) em C Conjunto simples round robin (média móvel) em C Como diagnóstico, eu quero exibir o número de ciclos por segundo no meu aplicativo. (Pense quadros por segundo em um atirador em primeira pessoa.) Mas eu não quero exibir o valor mais recente, ou a média desde o lançamento. O que eu quero calcular é a média dos últimos valores X. Round robin sheduling tempo de espera médio Oi, estou lendo o livro Silberschatz sobre o sistema operacional, 7ª edição. A teoria é boa, mas não há suporte para exercícios, nem explicação exaustiva. Estou tentando fazer o exercício 5.4, calcular o tempo médio de espera de assalto ao round robin. Implementando simples round-robin oi, eu tenho um conjunto ascendente de usuários com IDs. Eu quero atribuir um trabalho em um ciclo para cada usuário. isso é. Primeiro trabalho para U1, segundo U2. Para o U3. Meu problema é esse. Quando o segundo trabalho vem com o amplificador ao mesmo tempo, U1 completa seu trabalho. Esse segundo trabalho novamente é atribuído a U1 ins Como fazer um Round Robin ou Existe uma maneira mais simples do que Round Robin

No comments:

Post a Comment