2017-04-14 6 views
1

J'essaie d'appliquer certaines fonctions avec deux éléments adjacents dans un ensemble de données donné. Veuillez vous référer à l'exemple suivant.multi tâche à la fois en python

# I'll just make a simple function here. 
# In my real case, I send request to database 
# to get the result with two arguments. 

def get_data_from_db_with(arg1, arg2): 
    # write a query with arg1 and arg2 named 'query_result' 
    return query_result 

data = [arg1, arg2, arg3, arg4] 
result = [] 
for a, b in zip(data, data[1:]): 
    result.append(get_data_from_db_with(a, b)) 

Par exemple, si la longueur des données est 4 comme cela est le cas vu ci-dessus, je demande envoyer 3 fois à la base de données. Chaque demande prend environ 0,3 secondes pour récupérer les données, soit 0,9 seconde (0,3 seconde * 3 demandes) au total. Le problème est que le nombre de demandes augmente, tout comme le temps global. Ce que je veux faire est, si possible, envoyer toutes les demandes à la fois. Fondamentalement, ça va ressembler à ça.

Avec le code ci-dessus,

1) get_data_from_db_with(arg1, arg2) 
2) get_data_from_db_with(arg2, arg3) 
3) get_data_from_db_with(arg3, arg4) 

seront traitées consécutivement.


Ce que je veux faire, si possible, est d'envoyer des demandes en une seule fois, pas consécutivement. Bien sûr, le nombre de demandes reste inchangé. Mais la consommation globale de temps diminuera selon mon hypothèse.

Maintenant, je suis à la recherche d'asynchrones, multiprocessing et ainsi de suite. Tout commentaire ou commentaire serait extrêmement utile.

Merci d'avance.

Répondre

2

Threads est probablement ce que vous cherchez. En supposant que la plupart du travail get_data_from_db_with est en attente d'entrée/sortie, comme l'appel de base de données.

import threading 

def get_data_from_db_with(arg1, arg2): 
    # write a query with arg1 and arg2 named 'query_result' 
    current_thread = threading.current_thread() 
    current_thread.result = query_result 

data = [arg1, arg2, arg3, arg4] 
threads = [] 
for a, b in zip(data, data[1:]): 
    t = threading.Thread(target=get_data_from_db_with, args=(a,b)) 
    t.start() 
    threads.append(t) 

results = [] 
for t in threads: 
    t.join() 
    results.append(t.result) 

Notez que cette solution préserve même l'ordre dans results liste.

+0

Merci pour votre aide! J'ai une question sur l'utilisation de 'threading'. Pour autant que je sache, Python préfère le multitraitement au multithread donné GIL (verrou global d'interprète). J'ai peut-être tort, mais j'étais juste curieux. –

+0

@GeeYeolNahm Cela dépend totalement de ce que vous essayez de faire. GIL est disponible sur toutes les E/S, aussi longtemps que vous faites des E/S (des tâches gourmandes en CPU), alors les threads sont préférables aux processus. – freakish

+0

J'ai essayé le multi-threading et ça a marché! Il est devenu, en moyenne, 2 à 3 fois plus rapide. Oui tu avais raison, le multi-threading a travaillé sur ce cas avec mon environnement de travail. Merci encore, bizarre! –

1

Une alternative au multitraitement consiste à travailler sur la construction de la requête elle-même. Rechercher des façons de combiner les requêtes quelque chose comme, (arg1 and arg2) or (arg2 and arg3)..., essaient essentiellement d'aller chercher toutes les données requises dans un seul appel.

+0

Merci de partager votre pensée. Oui, j'ai fait une recherche en envoyant une demande comme vous l'avez mentionné. Je travaille toujours sur l'écriture d'une requête unique et l'analyse du résultat. J'ai utilisé [l'API multisearch elasticserach] (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html). Avant tout, je pense que l'envoi d'une requête surpasse l'envoi simultané de plusieurs requêtes! –