Estou desenvolvendo uma simulação de física e, como sou um iniciante em programação, continuo tendo problemas ao produzir programas grandes (principalmente problemas de memória). Eu sei sobre alocação e exclusão de memória dinâmica (nova / exclusão, etc.), mas preciso de uma abordagem melhor para estruturar o programa.
Digamos que estou simulando um experimento que está sendo executado por alguns dias, com uma taxa de amostragem muito grande. Eu precisaria simular um bilhão de amostras e atropelar elas.
Como uma versão super simplificada, diremos que um programa utiliza as voltagens V [i] e as soma em cinco:
ie NovoV [0] = V [0] + V [1] + V [2] + V [3] + V [4]
então NewV [1] = V [1] + V [2] + V [3] + V [4] + V [5]
então NewV [2] = V [2] + V [3] + V [4] + V [5] + V [6] ... e isso se aplica a um bilhão de amostras.
No final, eu teria V [0], V [1], ..., V [1000000000], quando os únicos que eu precisaria armazenar para a próxima etapa são os últimos 5 V [i] s.
Como excluir / desalocar parte da matriz para que a memória fique livre para uso novamente (digamos V [0] após a primeira parte do exemplo, onde ela não é mais necessária)? Existem alternativas para estruturar esse programa?
Eu ouvi falar do malloc / free, mas ouvi dizer que eles não devem ser usados em C ++ e que existem alternativas melhores.
Muito obrigado!
tldr; o que fazer com partes de matrizes (elementos individuais) Eu não preciso mais de uma quantidade enorme de memória?
V
vez de em uma nova matriz. Fundamentalmente, porém, acho que seu problema está em seus algoritmos ou em suas estruturas de dados e, como não temos detalhes, é difícil saber como fazê-lo com eficiência.Respostas:
O que você descreve, "suavização por cinco", é um filtro digital de resposta finita ao impulso (FIR). Esses filtros são implementados com buffers circulares. Você mantém apenas os últimos N valores, mantém um índice no buffer que informa onde está o valor mais antigo, substitui o valor mais antigo atual pelo mais recente em cada etapa e alterna o índice, circularmente, a cada vez.
Você mantém os dados coletados, que serão processados, em disco.
Dependendo do seu ambiente, este pode ser um daqueles lugares onde é melhor obter ajuda experiente. Em uma universidade, você coloca uma nota no quadro de avisos do Departamento de Ciência da Computação, oferecendo salários aos alunos (ou mesmo taxas de consultoria para estudantes) por algumas horas de trabalho, para ajudá-lo a analisar seus dados. Ou talvez você ofereça pontos de oportunidade de pesquisa de graduação. Ou alguma coisa.
fonte
Todo problema pode ser resolvido adicionando um nível adicional de indireção. Então faça isso.
Você não pode excluir parte de uma matriz em C ++. Mas você pode criar uma nova matriz contendo apenas os dados que deseja manter e excluir a antiga. Assim, você pode criar uma estrutura de dados que permita "remover" elementos que você não deseja da frente. O que ele realmente fará é criar uma nova matriz e copiar os elementos não removidos para a nova e excluir a antiga.
Ou você pode simplesmente usar
std::deque
, o que já pode efetivamente fazer isso.deque
, ou "fila dupla", é uma estrutura de dados destinada a casos em que você exclui elementos de uma extremidade e adiciona elementos à outra.fonte
std::deque
é o caminho a percorrerdeque
. Ou seja, armazenar e reutilizar alocações, conforme solicitado. Assim,deque
parece uma solução perfeitamente adequada para o problema.As respostas FIR e SMA que você obteve são boas no seu caso, no entanto, gostaria de aproveitar a oportunidade para avançar com uma abordagem mais genérica.
O que você tem aqui é um fluxo de dados: em vez de estruturar seu programa em 3 grandes etapas (obter dados, calcular, resultado de saída) que exigem o carregamento de todos os dados na memória de uma só vez, você pode estruturá-lo como um pipeline .
Um pipeline começa com um fluxo, o transforma e o empurra para uma pia.
No seu caso, o pipeline se parece com:
O C ++ tende a usar iteradores em vez de fluxos, mas, para ser honesto, os fluxos são mais fáceis de modelar (existe uma proposta para intervalos que seriam semelhantes aos fluxos):
E então, o pipeline se parece com:
Os fluxos nem sempre são aplicáveis (eles não funcionam quando você precisa de acesso aleatório aos dados), mas quando são, eles agitam: ao operar com uma quantidade muito pequena de memória, você mantém tudo no cache da CPU.
Em outra nota: parece que seu problema pode ser "embaraçosamente paralelo", convém dividir seu arquivo grande em pedaços (lembre-se, para processar pelo Windows 5, é necessário ter 4 elementos comuns em cada limite) e processe os pedaços em paralelo.
Se a CPU for o gargalo (e não a E / S), você poderá acelerá-la iniciando um processo por núcleo depois de dividir os arquivos em quantidades aproximadamente iguais.
fonte