Найти - Пользователи
Полная версия: На стандартном примере потоков не вижу performance
Начало » Python для экспертов » На стандартном примере потоков не вижу performance
1
MichaelN
Привет, Всем.
Помогите разобраться.
Имеется 50 файлов по 100 000 тыс. записей
В них буду искать слова и подсчитывать из количество.

#!/usr/bin/env python
# coding=utf-8

import threading as t
import time, re
import Queue

def parseit( num ):
global total
log = open('log_%d' % num)
lines = log.readlines()

for line in lines:
if re.search('miki', line):
total += 1

class Parse( t.Thread ):
def __init__(self, work_queue):
self.work_queue = work_queue
t.Thread.__init__(self)

def run(self):
while True:
filename = self.work_queue.get()
self.process( filename )
self.work_queue.task_done()

def process(self,filename):
global total
log = open(filename)
lines = log.readlines()

for line in lines:
if re.search('miki', line):
total += 1


def test1():
global total
total = 0
for i in range(1,50):
parseit(i)
print total

def test2():
global total
THREAD = 3
total = 0
work_q = Queue.Queue()
lst_file = ['log_%d' % x for x in range(1,50) ]

for item in lst_file:
work_q.put( item )

for i in range( THREAD ):
tr = Parse(work_q)
tr.setDaemon(True)
tr.start()
work_q.join()
print total

start = time.time()
test1()
print 'Послед.: %f'.decode('utf-8') % (time.time() - start)
start = time.time()
test2()
print 'Потоки: %f'.decode('utf-8') % (time.time() - start)
Вот мой вывод:
Microsoft Windows
© Корпорация Майкрософт (Microsoft Corp.), 2009. Все права защищены.
E:\DevProject\etest>thtest.py
815220
Послед.: 12.529000
789345
Потоки: 18.775000

E:\DevProject\etest>thtest.py
815220
Послед.: 12.357000
789265
Потоки: 18.825000

E:\DevProject\etest>thtest.py
815220
Послед.: 12.237000
789370
Потоки: 20.780000
Объясните мне почему.
doza_and
1 Почитайте про GIL. Потоки в питоне выполняются одновременно, но не для питоновского кода. Используйте multiprocessing там кстати есть и map-reduse который можно тут использовать.

2 Читайте не по строкам, а все целиком
3 Регулярные выражения компилируйте и применяйте к длинной строке
4 в случае “miki” быстрее будет работать поиск подстроки.
5 Оно у вас неправильно работает если в строке несколько “miki” (или может быть правильно, тогда совет 2 не подойдет).
Isem
Последовательное чтение файлов выполняется заметно быстрее, чем постоянное перепрыгивание с одного на другой и обратно (перемещение магнитной головки диска с дорожки на дорожку требует кучу времени). Читайте файлы последовательно, а вот поиск делайте параллельно в разных нитках. Чтение файла сразу в нескольких нитках будет всегда медленнее, чем чтение того же файла в одной нитке. Головка то одна.
MichaelN
Этот пример я не из головы выдумал он был дан в качестве пример в журнале LINUX-FORMAT
Вот ссылка http://wiki.linuxformat.ru/index.php/LXF82:Python
Вот название пример THREAD-TEST.PY
Хороший пример с я нашел в книги Python в системном администрировании UNIX и Linux.
Может кому пригодится.
Опрос сети.

#!/usr/bin/python
# -*- coding: utf-8 -*-

#

from threading import Thread
import subprocess
from Queue import Queue
import time

num_threads = 5
queue1 = Queue()
queue2 = Queue()
ips = [ '192.168.1.%d' %x for x in range( 20 ) ]

def pinger(i, q):
#опрос подсети
while True:
ip = q.get()
print "Thread %s: Pinging %s" % (i, ip)
ret = subprocess.call('ping -n 1 %s' % ip, shell=True, stdout=False)
if ret == 0:
print "%s: is alive\n" % ip
else:
print "%s: did not respond\n" % ip
q.task_done()

def test1():
for ip in ips:
queue1.put(ip)

for i in range(num_threads):
worker = Thread(target=pinger, args=(i, queue1))
worker.setDaemon(True)
worker.start()

print "Main Thread Waiting'"
queue1.join()

def test2():
start = time.time()
for ip in ips:
queue2.put(ip)

for x in range(10):
ipp = queue2.get()
print 'ping: %s' % ipp
p = subprocess.call('ping -n 1 %s' % ipp, shell=True, stdout=False)
queue2.task_done()

start1 = time.time()
test1()
print 'Task1: {0}'.format( time.time() - start1 )

start2 = time.time()
test2()
print 'Task2: {0}'.format( time.time() - start2 )
Chrizt
MichaelN,
А Вы в курсе, что Ваши принты тоже неслабо задерживают программу =)
Особенно это заметно в IDLE в шелле.

doza_and
Потоки в питоне выполняются одновременно, но не для питоновского кода.
А вот это я вообще не понял. Как-то взорвало мозг.
Про GIL я в курсе, читал, но Ваше предложение вообще не сдюжил :(
doza_and
:) Извините пробовал коротко выразиться
см например http://habrahabr.ru/blogs/python/84629/

Потоки в питоне выполняются одновременно <=> “Python threads — это настоящие потоки (POSIX threads или Windows threads), полностью контролируемые ОС.”

но не для питоновского кода <=> “В этом вся загвоздка: в любой момент может выполняться только один поток Python. Глобальная блокировка интерпретатора — GIL — тщательно контролирует выполнение тредов.”
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB