Exemplos de paralelização em python

De modo geral, a paralelização permite executar várias funções ao mesmo tempo. Ela pode ser muito útil para tornar um código com muitos ciclos mais rápido, além de permitir mensagens durante scripts com um longo tempo de execução. Os scripts de exemplo apresentados nesse post devem tornar um processamento com loop mais rápido. Para ver mais sobre a teoria de processamento em paralelo e métodos em Python, clique no link.

Todos os códigos estão disponíveis no Github/viniroger. Para comparar o tempo de execução dos códigos com e sem paralelização, foram criados métodos para monitorar o tempo de execução de cada função. A classe “Timer” contém os métodos “start” e “stop”, que inicializa e finaliza a cronometragem, respectivamente – a última também imprime quantos segundos foram contabilizados. Para simular o atraso de um acesso ao disco, requisição em rede ou cálculo mais longo, são implementados os métodos “time.sleep” em pontos do código.

Loop interno à função – multi_loop_interno.py

Caso o loop esteja dentro da função, pode-se quebrar um loop que vai de 0 a n em l listas, cada uma com n/l elementos. Desse modo, cada processador receberá uma lista de entradas, cada uma sendo executada separada e simultaneamente. Note que a ordem em que os elementos são executados não é importante. Caso o número de pedaços seja maior que o número de núcleos de processamento, os novos pedaços são executados nos núcleos ociosos.

No script, a função f calcula a soma quadrática dos valores de uma lista. Já a função f_amp executa a função f mas paralelizando os diferentes pedaços da lista.

Loop externo à função – multi_loop.py

Caso o loop esteja fora da função, é possível aplicar diretamente o método “starmap” no Pool. Além do nome da função, o método deve receber como parâmetro os argumentos da função. No script, foi criada uma lista (a_list) com os números a serem alterados no loop. Também foi criada uma lista (b_list) com vários tipos de argumentos para uma função e que devem permanecer constantes em todas as iterações.

Para organizar os argumentos, pode-se usar os métodos “zip”, que retorna uma sequência de tuplas, e “itertools.repeat”, que repete uma lista com os argumentos fixos para cada valor identificador do loop (por exemplo, n = 1, 2, 3…).

O multiprocessamento precisa serializar (pickle) as entradas para passá-las para o novo processo que executará a função “f_amp”. No caso de um objeto do conjunto de dados não ser compatível, deve aparecer um erro do tipo “MFDataset is not picklable”. Uma possível solução alternativa seria usar o multiprocessamento com outra função que lê o conjunto de dados e chama a função nele.

Loop com multithread – thread.py

No script, a classe “minhaThread” herda a classe “threading.Thread”, recebendo um nome e um contador. O método “run” imprime mensagens para acompanhamento na tela e executa o método a ser paralelizado, chamado “processo”. Nele, deve imprimir uma frase, contendo os argumentos recebidos, e atualizar um contador regressivo.

Loop em linhas de dataframe – multi_df.py

O mutiprocessamento não pode ser executado de forma interativa, de modo que a funcionalidade dentro deste pacote requer a parte __name__ == “__main__” no Windows, com o método “freeze_support”. Isso é para garantir que o módulo principal possa ser importado com segurança por um novo interpretador Python – por exemplo, por um processo filho.

São criadas duas variáveis globais relacionadas aos dados de entrada (df_in) e de saída (df_out) no formato dataframe. O arquivo de exemplo (sample.csv) foi criado a partir da amostra randômica de uma dataframe bem maior através dos seguintes comandos em bash:

awk -F"," -v OFS="," '{print $1,$2,$3,$4}' data.csv | sort -R | head -100 | sed -i '1 i\latitude,longitude,time,value' sample.csv

Na função principal, são criadas as variáveis com o número de processadores e com uma lista de 0 até o número de linhas da dataframe de saída. A função “run_multiprocessing” recebe a função a ser executada (loop), a lista com os valores de loop (x_ls) e o número de processadores (n_processors) para executar cada elemento do loop. Essa função está dentro da chamada do método tqdm, que imprime uma barra que mostra o progresso da aplicação através do percentual com relação ao número total de elementos.

A função loop seleciona as linhas da dataframe que possuam os mesmos valores de latitude e longitude (ou seja, o pixel) e executa um cálculo com esses valores, o qual será o retorno da função juntamente com as coordenadas geográficas.

Os valores retornados serão salvos em seus devidos lugares na dataframe de saída (função df_update). Também existem as funções para salvar essa dataframe de saída em um arquivo CSV ou NetCDF.

Fontes

One comment

Leave a Reply

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.