Atualizar um DataFrame em diferentes processos python em tempo real

8

Então, digamos que você tenha um processo Python que colete dados em tempo real com cerca de 500 linhas por segundo (isso pode ser paralelizado ainda mais para reduzir para cerca de 50 ps) de um sistema de filas e anexá-lo a DataFrame:

rq = MyRedisQueue(..)
df = pd.DataFrame()
while 1:
    recv = rq.get(block=True)
    # some converting
    df.append(recv, ignore_index = True)

Agora, a pergunta é: como utilizar as CPUs com base nesses dados? Portanto, estou plenamente consciente das limitações do GIL , e olhou para multiprocessamento Gerente de namespace , aqui também , mas parece que existem algumas desvantagens em relação à latência na trama de dados centerally espera . Antes de escavar para ele, eu também tentou pool.mapque eu que reconheceu a aplicar pickleentre os processos, que é maneira de retardar e tem muita sobrecarga.

Então, depois de tudo isso, eu finalmente me pergunto, como (se) uma inserção de 500 linhas por segundo (ou mesmo 50 linhas por segundo) pode ser transferida para diferentes processos com algum tempo de CPU restante para aplicar estatísticas e heurísticas nos dados na criança processos?

Talvez seja melhor implementar um soquete tcp personalizado ou sistema de filas entre os dois processos? Ou existem algumas implementações pandasou outras bibliotecas para realmente permitir um acesso rápido ao único grande quadro de dados no processo pai ? Eu amo pandas!

gies0r
fonte
Deseja executar as estatísticas apenas nos blocos de 50 a 500 linhas que são novas a cada segundo e anexá-las continuamente a um grande DF? O DF grande deve ser armazenado ou você precisa de mais processamento em tempo real para ser executado nele?
Ronald Luc
@RonaldLuc Se for um requisito necessário, eu o limitaria a estatísticas nas novas 50 a 500 linhas, sim. Eu poderia manter médias e altas / baixas em variáveis ​​extras para acompanhar os dados existentes no grande DataFrame.
gies0r

Respostas:

4

Antes de começarmos, devo dizer que você não nos contou muito sobre seu código, mas tem esse objetivo de transferir apenas 50/500 novas linhas por segundo para o processo filho e tentar criar esse grande DataFrame processo filho.

Estou trabalhando em um projeto exatamente igual ao seu. O Python possui muitas implementações de IPC, como Pipee Queuecomo você sabe. Shared Memorysolução pode ser problemática em muitos casos, a documentação oficial do AFAIK python alertou sobre o uso de memórias compartilhadas.

Na minha experiência, a melhor maneira de transformar dados entre apenas dois processos é Pipe, para que você possa selecionar o DataFrame e enviá-lo para o outro ponto final da conexão. Eu sugiro fortemente que você evite TCPsockets ( AF_INET) no seu caso.

Os pandas DataFramenão podem ser transformados em outro processo sem serem conservados em conserva. por isso, recomendo que você transfira os dados brutos como tipos dictinternos, como no lugar do DataFrame. Isso pode tornar a pickle e a remoção mais rápidas e também possui menos pegadas de memória.

AmirHmZ
fonte
Agradeço sua resposta @AmirHmZ! Especialmente o link para o benchmark é bom (e as ferramentas em torno dele, que eu ainda não conhecia). Uma solução na Shared Memoryárea - que, esperançosamente, pode lidar com muitos processos de leitura dos processos filhos, enquanto os principais processos estão anexados a ele - poderia fazê-lo pelo que vejo, se dificilmente restringir os acessos de gravação ao processo pai.
gies0r 4/04
.. Mas eu não sei, se shared memoryestá em algum tipo de block stateescrita para ele? Isso significaria que os processos filho não podem ler o DataFrame, enquanto o processo pai é anexado a ele (o que quase sempre será).
gies0r 4/04
@ gies0r Desculpe pela minha inatividade. Se você pretende usar a Shared Memorysolução, sincronize os processos filhos com o processo do fornecedor. Isso poderia ser feito por multiprocessing.Lock: docs.python.org/3/library/…
AmirHmZ
0

Paralelização em pandas é provavelmente melhor tratada por outro mecanismo.

Dê uma olhada no projeto Koalas da Databricks ou do DataFrame da Dask .

jorijnsmit
fonte
Bem .. É uma quantidade enorme de código a ser revisada e corrigida ... O Dasks parece ter uma boa adaptação, mas ainda assim é uma tonelada de trabalho. Você conhece um exemplo em que um intervalo de carregamento / atualização de dados como o mencionado na pergunta foi implementado / documentado?
gies0r 02/04
Usei o Dask para processar conjuntos de dados de mais de 200 GB em espaço paralelo e com pouca memória, mas não estava online. O Dask é basicamente muitos quadros de dados de pandas empilhados uns sobre os outros.
Ronald Luc
@RonaldLuc que tipo de operações você fez na sua máquina local?
Datanovice em 3/04
Carregue do parquet, operações numéricas em linhas, cálculo de geolocalizações, alguma operação no "local pandas DataFrame" ( df.map_partitions) e, em seguida, groupbyindexe (importante para o desempenho no Dask), salve como CSV.
Ronald Luc
0

Uma solução simples seria separar o processo em dois estágios diferentes. Use o Asyncio para receber os dados de maneira não-bloqueante e executar suas transformações dentro disso. O segundo estágio consumiria uma fila assíncrona para criar o DataFrame. Isso pressupõe que você não precisa do DataFrame disponível para um processo diferente enquanto estiver recebendo dados da Fila Redis.

Aqui está um exemplo de construção de um modelo de produtor / consumidor com o Asyncio

arshit arora
fonte