Saturday 23 December 2017

Média móvel de buffer circular


Eu usei-o para um registro na memória com um tamanho restrito. Por exemplo, o aplicativo escreveria entradas de log durante o processamento de solicitações de usuário. Sempre que ocorreu uma exceção (que seria prejudicial para o processamento) os registros de log atualmente na memória seria despejado junto com ele. O benefício de um buffer circular é que você não precisa de quantidades infinitas de memória, já que as entradas mais antigas são substituídas automaticamente. O challange é, que você precisa encontrar um tamanho adequado para o seu usecase. No exemplo acima, seria muito infeliz quando o registro de log com as informações mais vitais sobre a exceção já teria sido substituído. Algumas aplicações de sistema têm ferramentas para permitir que você extraia o conteúdo atual do buffer na demanda, e não apenas quando seria extraído automaticamente (se alguma vez). Eu acredito que ETW eo registro de estresse CLRs. Entre muitos outros sistemas kernel ou high-performance tracelogging, são implementadas dessa forma. O conceito de usar esses buffers para tracinglogging na memória é realmente muito comum (para não dizer que este é o único uso - certamente não), porque é muito mais rápido do que os registros escritos para uma base de dados que você pode nunca estar interessado, a menos que um Erro ocorre. E em uma nota relacionada, ele conserva o espaço no disco rígido. Os buffers circulares são bons para fluxos de dados em série em sistemas incorporados. Os microcontroladores geralmente têm um UART para lidar com um byte serial vindo, estes precisam ser armazenados em ordem e tratados mais tarde (bytes geralmente vêm em uma taxa mais rápida do que eles podem ser manipulados). O buffer efetivamente divide a resposta de tempo crítico necessária (quando os bytes vêm em, em microssegundos) para a resposta não cronometrada crítica para toda a mensagem (por exemplo, exibindo a mensagem que veio, em milissegundos), por exemplo: 1) A recepção de um byte a UART pode gerar uma interrupção para que o software responde rapidamente tomando o byte recebido e empurra-lo para o final do buffer. 2) As rotinas de software em segundo plano podem então verificar regularmente se o buffer tem alguma coisa ainda e esvaziá-lo conforme necessário. Como o tamanho do buffer circular pode ser definido pré-compilação o tamanho é então limitado. Isso ajuda a melhorar a eficiência do espaço e deve eliminar a corrupção de memória em um trade off para quantos bytes podem ser recebidos antes dos dados começarem a se perder. Eu sei que isso é batota, mas wikipedia tem uma explicação muito boa. Um buffer circular, buffer cíclico ou buffer de anel é uma estrutura de dados que usa um único buffer de tamanho fixo como se estivesse conectado de ponta a ponta. Essa estrutura se presta facilmente a buffering fluxos de dados Um exemplo que possivelmente poderia usar um sobrescrever buffer circular é com multimídia. Se o buffer for usado como buffer limitado no problema produtor-consumidor, então é provavelmente desejado para o produtor (por exemplo, um gerador de áudio) substituir dados antigos se o consumidor (por exemplo, a placa de som) não conseguir manter-se momentaneamente. Outro exemplo é o método de síntese de guia de onda digital que usa tampões circulares para simular eficientemente o som de cordas vibratórias ou instrumentos de sopro. Com relação à comparação com listas duplas, eu imagino que realmente depende do que você está usando a lista para. A implementação de amortecedores cirulares parece ser mais complexa, por favor (novamente) consulte a página wiki isso explica a implementação, considerações etc e também mostra código de exemplo. Respondeu Mar 31 10 at 14:25Eu sei que isso é alcançável com o impulso como por: Mas eu realmente gostaria de evitar usar impulso. Eu tenho googled e não encontrei qualquer exemplos adequados 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 de 1000 mais recentes como uma amostra de dados. Qual é a maneira mais fácil de conseguir isso que eu experimentei com o uso de uma matriz circular, média móvel exponencial e uma média móvel mais simples e descobriu que os resultados da matriz circular adequado às minhas necessidades. Se suas necessidades são simples, você pode apenas tentar usar uma média móvel exponencial. Simplificando, você faz uma variável de acumulador, e como seu código olha para 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. Hmm, Im realmente não tenho certeza que isso é adequado para você, agora que Ive colocá-lo aqui. O problema é que 1000 é uma janela muito longa para uma média móvel exponencial Não tenho certeza se há um alfa que iria espalhar a média nos últimos 1000 números, sem subfluxo no cálculo do ponto flutuante. Mas se você quisesse uma média menor, como 30 números ou assim, esta é uma maneira muito fácil e rápida de fazê-lo. Respondeu 12 de junho 12 em 4:44 1 em seu borne. A média móvel exponencial pode permitir que o alfa seja variável. Portanto, isto permite que ele seja usado para calcular médias de base de tempo (por exemplo, bytes por segundo). Se o tempo desde a última actualização do acumulador for superior a 1 segundo, deixe alfa ser 1.0. Caso contrário, você pode deixar alfa ser (usecs desde a última atualização1000000). Ndash jxh 12 de junho de 12 às 6:21 Basicamente eu quero acompanhar a média móvel de um fluxo em curso de um fluxo de números de ponto flutuante usando os mais recentes números de 1000 como uma amostra de dados. Observe que o abaixo atualiza o total como elementos como addedreplaced, evitando costal O (N) traversal para calcular a soma - necessária para a média - on demand. Total é feito um parâmetro diferente de T para suporte, e. Usando um longo longo quando totalizando 1000 s longos, um int para char s, ou um dobro ao total float s. Este é um pouco falho em que numsamples poderia ir passado INTMAX - se você se importa que você poderia usar um unsigned longa. Ou usar um membro de dados bool extra para gravar quando o recipiente é preenchido pela primeira vez enquanto ciclismo numsamples ao redor da matriz (melhor então renomeado algo inócuo como pos). Respondida em 12 de junho de 12 às 5:19, assume-se que o operador de quotvoid (amostra T) é realmente operador quotvoid (T amostra) quot. Ndash oPless Jun 8 14 at 11:52 oPless ahhh. Bem manchado. Na verdade, eu quis dizer para ser vazio operador () (T amostra), mas é claro que você poderia usar qualquer nota que você gostava. Will fix, obrigado. Ndash Tony D Jun 8 14 às 14: 27Uma das principais aplicações para a placa Arduino é a leitura e registro de dados de sensores. Por exemplo, um monitora a pressão a cada segundo do dia. Como altas taxas de amostragem muitas vezes gera picos nos gráficos também se deseja ter uma média das medições. Como as medições não são estáticas no tempo o que muitas vezes precisamos é de uma média de corrida. Esta é a média de um determinado período e muito valioso quando se faz análise de tendências. A forma mais simples de uma média em execução pode ser feita por um código que se baseia na média anterior: Se não se deseja usar matemática em ponto flutuante - como isso ocupa a memória e diminui a velocidade - pode-se fazer o mesmo completamente no domínio inteiro. A divisão por 256 no código de exemplo é um deslocamento-direito 8, que é mais rápido do que a divisão por e. 100. Isto é verdade para cada poder de 2 como divisor e um só deve ter cuidado a soma dos pesos é igual ao poder de 2. E, claro, deve-se ter cuidado não há transbordamento intermediário (considere usar unsigned long) Se você precisar Uma média de execução mais precisa, in concreto das últimas 10 medições, você precisa de uma matriz (ou lista vinculada) para mantê-los. Esta matriz age como um buffer circular e com cada nova medição a mais antiga é removida. A média de execução é calculada como a soma de todos os elementos dividida pelo número de elementos na matriz. O código para a média em execução será algo como isto: Desvantagem deste código é que a matriz para armazenar todos os valores pode se tornar bastante grande. Se você tem uma medição por segundo e você quer uma média de execução por minuto você precisa de uma matriz de 60 uma média por hora precisaria de uma matriz de 3600. Isso não poderia ser feito desta maneira em um Arduino, pois ele só tem 2K de RAM. No entanto, através da construção de uma média de 2 estágios que pode ser abordado muito bem (renúncia: não para todas as medições). No código psuedo: Como uma nova matriz estática interna é necessária para cada função runningAverage, isso grita para ser implementado como uma classe. Biblioteca RunningAverage A biblioteca runningAverage cria uma classe da função acima para que ela possa ser usada várias vezes em um sketch. Desacopla a função add () e avg () para ser um pouco mais flexível, e. Um pode chamar a média várias vezes sem adicionar uma coisa. Observe que cada instância da classe adiciona sua própria matriz para realizar medições e que isso adiciona até o uso de memória. A interface da classe é mantida o menor possível. Nota: com a versão 0.2 os nomes dos métodos são todos mais descritivos. Um pequeno esboço mostra como ele pode ser usado. Um gerador aleatório é usado para imitar um sensor. Em setup () o myRA é limpo para que possamos começar a adicionar novos dados. Em loop () primeiro um número aleatório é gerado e convertido em um flutuador a ser adicionado ao myRA. Em seguida, o runningAverage é impresso para a porta serial. Um também poderia exibi-lo em algum LCD ou enviar mais ethernet, etc Quando 300 itens são adicionados myRA é limpo para começar tudo de novo. Para usar a biblioteca, crie uma pasta em seu SKETCHBOOKPATHlibaries com o nome RunningAverage e coloque o. h e. cpp lá. Opcionalmente, faça um subdiretório de exemplos para colocar o aplicativo de amostra. 2017-01-30: versão inicial 2017-02-28: fixo destruidor em falta no arquivo. h 2017-02-28: construtor padrão removido 2017--. Adicionado fillValue () refactored para publicação 2017-07-03: adicionado código de proteção de memória - se matriz interna não pode ser alocada tamanho Torna-se 0. Isso é para resolver o problema descrito aqui - forum. arduino. ccindex. phptopic50473.msg1790086msg1790086 - Teste extensivamente. Classe de modelo RunningAverage. h RunningAverage. cpp

No comments:

Post a Comment