Multithreading en Python

B

El script consiste en duplicar x archivos a partir de uno dado (un xml). Se setea un valor único a un par de campos en cada archivo.

Bien, eso ya lo tengo funcionado. Lo que quiero es acelerar el proceso usando threads.

    
with open(args.template, 'r') as f_in: template_content = f_in.read() msg_per_thread = int(args.messages / args.threads) remaining_messages = args.messages % args.threads print('[%s] Duplicating messages...' % (time.strftime("%H:%M:%S", time.localtime()))) with ThreadPoolExecutor() as executor: for thread in range(1, args.threads+1): end = msg_per_thread * thread start = (end - msg_per_thread) + 1 if thread == args.threads: end += remaining_messages executor.submit(duplicate, template_content, msg_name, msg_dir, start, end) print('[%s] Duplicating messages finished' % (time.strftime("%H:%M:%S", time.localtime())))

La función duplicate toma los parametros start y end para luego hacer un bucle en ese rango. En cada ciclo del bucle se escribe el nuevo archivo.

def duplicate(template_content, msg_name, msg_dir, n_msg_start, n_msg_end):
    for num_msg in range(n_msg_start, n_msg_end + 1):
        num_msg = str(num_msg)
        result = template_content.replace('{env-id}', 'MESSAGE_' + num_msg, 1)
        result = result.replace('{sdr-reference}', num_msg)
        msg = msg_dir + '/' + msg_name + '_' + num_msg + '.xml'
        with open(msg, 'w') as f_out:
            f_out.write(result)

Lo que estoy testeandolo y no veo ninguna mejora... Da igual el valor del numero de threads que le de, siempre me tarda lo mismo.
Estoy usando bien el ThreadPoolExecutor ? Me falta algo?

r2d2rigo

Estas seguro que tu cuello de botella esta en la CPU? Porque puede ser que estes ahogando el disco duro y por eso te tarde lo mismo a pesar de usar hilos.

2 respuestas
B

#2 o sea, lo que quiero acelerar es la escritura precisamente. Pero claro, supongo que eso ya estará a tope y usar threads no mejorará nada

1 respuesta
EnderFX

#3 Si el factor limitante es I/O a/del disco duro, me temo que la única solución es comprarte otro disco duro y escribir a él en paralelo :/. Pero no sé, tampoco sé muy bien qué es lo que te está limitando, aunque podría ser eso.

1 respuesta
B

Todo indica a que sucede lo que comenta #2 ... ¿porque necesitas tenerlo troceado todo en el disco? ¿Podrías tener otra estructura? En vez de un programa que trocee igual crear dos. Uno para estructurar los datos en un único archivo y otro para consultar y si eso, trocear ese pedazo que se quiere.
Si el diseño actual es algo imperativo por razones externas pues como comenta #4 ... mirar de soluciones con discos duros, igual alguna configuración RAID para acelerar al escritura.

B

La idea es que el script lo use el equipo de QA para crear archivos de testing que luego serán consumidos por una aplicación. No es nada que sea crítico. Pensaba que podría optimizar por ahí, pero se quedará asins.

Gracias

eondev

Habiendo leído el hilo en diagonal, has probado con la lib de multiprocessing? Sin pensarlo mucho muy probable que el GIL esté actuando y por eso no tengas ninguna ganancia.

Usuarios habituales