Python - параллелизм

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Olej » 06 авг 2013, 17:38

Виктория писал(а):Windows вроде больше тяготеет к потокам. Результаты могут быть совсем другие?

Где бы ещё найти восьмиядерный проц? ))
Виктория, 8-ми ядерный проц - это, возможно и здорово...
Но я бы вас попросил, если это возможно, выполнить программу в Windows, но в Pyhon 2.X не в (3.X) ... что гораздо проще чем 8-ми ядерный проц ;-).

Потому как 3.Х это, конечно, более современно, но основная масса проектов и приложений пока выполняется, всё таки, в Pyhon 2.X.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Olej » 06 авг 2013, 17:47

Olej писал(а):P.P.S. Как и должно ожидать, fork() в Windows нет и быть не может...
Но меня удивляет то, что это выразилось не в синтаксической ошибке при обращении к модулю os, а то, что там этот вызов есть, а закончился он ошибкой исполнения!
В встроенной документации "Python v3.3.2 documentation", которая в Windows инсталлируется вместе с пакетом Python, находим:
os.fork()
Fork a child process. Return 0 in the child and the child’s process id in the parent. If an error occurs OSError is raised.
...
Availability: Unix.
Т.е. вот каким путём они пошли: вызовы присутствуют в любой реализации, но работают они только в тех ОС, где подобные действия предусмотрены (а в других там стоят просто заглушки, возвращающие ошибки).

Так же точно, как в том же модуле есть вызовы, которые работают только в Windows:
os.startfile(path[, operation])
Start a file with its associated application.
...
Availability: Windows.
Так же как приводимый там же в документации пример того, что с 2.7 и даже 3.2 делалось совсем по-другому:

Код: Выделить всё

import ctypes

def kill(pid):
    """kill function for Win32"""
    kernel32 = ctypes.windll.kernel32
    handle = kernel32.OpenProcess(1, 0, pid)
    return (0 != kernel32.TerminateProcess(handle, 0))

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Olej » 06 авг 2013, 22:21

Olej писал(а):
Виктория писал(а):Windows вроде больше тяготеет к потокам. Результаты могут быть совсем другие?
Но такое изменение поведения, я думаю (практически уверен!) связано не с Linux/Windows, а с тем, что эти прогоны (Windows) я делаю в Python 3, где и говорили, что что-то с GIL переделали:

Код: Выделить всё

c:\Python-test\pytspeed>python -V
Python 3.3.2
Специально у себя в Linux установил Python 3.X параллельно с 2.Х (сильно не хотелось загаживать систему непотребным), ... прямо из репозитария, по минимуму, что-то на манер:

Код: Выделить всё

bash-4.2$ sudo yum install python3.i686 python3-devel.i686
...
Установлено:
  python3.i686 0:3.2.3-7.fc17                         python3-devel.i686 0:3.2.3-7.fc17
Установлены зависимости:
  python3-libs.i686 0:3.2.3-7.fc17
Выполнено!
New leaves:
  python3-devel.i686

Код: Выделить всё

bash-4.2$ which python3
/usr/bin/python3
bash-4.2$ python3 -V
Python 3.2.3
В качестве тестового приложения взял непосредственно файл mthrsw.py (прикреплённый выше), скачанный из Windows - ещё одна проверка совместимости и переносимости... Переименую в mthrs3.py и изменяю только первую строку, указывающую интерпретатор:

Код: Выделить всё

#!/usr/bin/python3
# -*- coding: utf-8 -*-
...
Проверка:

Код: Выделить всё

bash-4.2$ ./mthrs3.py
число выполнений 2
число циклов в выполнении 10000000
============ последовательное выполнение ============
время 6.44 секунд
================ параллельные потоки ================
время 8.79 секунд
=============== параллельные процессы ===============
время 4.05 секунд
Довольно загадочное поведение ... практически не отличающееся от 2.7...
Если что-то и поменялось с глобальной блокировкой GIL, то где-то между версиями 3.2 и 3.3.

Аватара пользователя
Виктория
Писатель
Сообщения: 113
Зарегистрирован: 28 дек 2012, 14:05
Откуда: Самара
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Виктория » 07 авг 2013, 12:30

Olej писал(а):
Виктория писал(а):Windows вроде больше тяготеет к потокам. Результаты могут быть совсем другие?

Где бы ещё найти восьмиядерный проц? ))
Виктория, 8-ми ядерный проц - это, возможно и здорово...
Но я бы вас попросил, если это возможно, выполнить программу в Windows, но в Pyhon 2.X не в (3.X) ... что гораздо проще чем 8-ми ядерный проц ;-).

Потому как 3.Х это, конечно, более современно, но основная масса проектов и приложений пока выполняется, всё таки, в Pyhon 2.X.
Windows XP SP3, Python 2.7.5, а процессор у меня всего лишь Intel Atom N270 1.6 ГГц (одноядерный, но с технологией HyperThreading).
Выполняю файл mthrs.py с параметрами по умолчанию - 6.19 s (последовательно), 6.38 s (параллельные потоки), процессы отказывается выполнять.
Ещё и не получилось с печатью кириллицы, только вот так

Код: Выделить всё

С+РёС_Р>Р_ Р_С<РїР_Р>Р_РчР_РёР№ 2
С+РёС_Р>Р_ С+РёРєР>Р_Р_ Р_ Р_С<РїР_Р>Р_РчР_РёРё 10000000
============ РїР_С_Р>РчР_Р_Р_Р°С'РчР>С_Р_Р_Рч Р_С<РїР_Р>Р_РчР_РёРч ============
Р_С_РчР_С_ 6.19 С_РчРєС_Р_Р_
================ РїР°С_Р°Р>Р>РчР>С_Р_С<Рч РїР_С'Р_РєРё ================
Р_С_РчР_С_ 6.38 С_РчРєС_Р_Р_
=============== РїР°С_Р°Р>Р>РчР>С_Р_С<Рч РїС_Р_С+РчС_С_С< ===============
error: create child process

Последний раз редактировалось Виктория 07 авг 2013, 12:46, всего редактировалось 1 раз.

Аватара пользователя
Виктория
Писатель
Сообщения: 113
Зарегистрирован: 28 дек 2012, 14:05
Откуда: Самара
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Виктория » 07 авг 2013, 12:39

Olej писал(а):
Виктория писал(а): Где бы ещё найти восьмиядерный проц? ))
У меня нет под рукой 8-ядерного проца ;-) ... максимум, что нашлось сразу - это вот это:

Код: Выделить всё

olej@atom:~/2013-WORK$ cat /proc/cpuinfo | grep proc
processor       : 0
processor       : 1
processor       : 2
processor       : 3
olej@atom:~/2013-WORK$ cat /proc/cpuinfo | grep 'model name'
model name      : Intel(R) Atom(TM) CPU  330   @ 1.60GHz
model name      : Intel(R) Atom(TM) CPU  330   @ 1.60GHz
model name      : Intel(R) Atom(TM) CPU  330   @ 1.60GHz
model name      : Intel(R) Atom(TM) CPU  330   @ 1.60GHz
Это "минималистичный" Intel Atom, и у него, конечно, не 4 ядра, а 2 ядра, но с hyperthreading ... и, в принципе, он на них распределяет выполнение потоков (отчасти, где может)...
И стоят там не совсем и свежие (это Ubuntu 10.04):

Код: Выделить всё

olej@atom:~/2013-WORK$ u_n_a_m_e -a
Linux atom 2.6.32-45-generic #100-Ubuntu SMP Wed Nov 14 10:41:11 UTC 2012 i686 GNU/Linux
olej@atom:~/2013-WORK$ python -V
Python 2.6.5
Это даже интереснее ... разные версии:

Код: Выделить всё

olej@atom:~/2013-WORK/python/parallel/pytspeed/mthrs$ ./mthrs.py
число выполнений 2
число циклов в выполнении 10000000
============ последовательное выполнение ============
время  6.36 секунд
================ параллельные потоки ================
время  9.80 секунд
=============== параллельные процессы ===============
время  3.45 секунд
У нас одинаковая тактовая частота у процессоров Intel Atom, так что ещё и по абсолютным значениям замеров времени можно сравнить.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Olej » 07 авг 2013, 20:04

Виктория писал(а): Ещё и не получилось с печатью кириллицы, только вот так

Код: Выделить всё

С+РёС_Р>Р_ Р_С<РїР_Р>Р_РчР_РёР№ 2
С+РёС_Р>Р_ С+РёРєР>Р_Р_ Р_ Р_С<РїР_Р>Р_РчР_РёРё 10000000
============ РїР_С_Р>РчР_Р_Р_Р°С'РчР>С_Р_Р_Рч Р_С<РїР_Р>Р_РчР_РёРч ============
Р_С_РчР_С_ 6.19 С_РчРєС_Р_Р_
================ РїР°С_Р°Р>Р>РчР>С_Р_С<Рч РїР_С'Р_РєРё ================
Р_С_РчР_С_ 6.38 С_РчРєС_Р_Р_
=============== РїР°С_Р°Р>Р>РчР>С_Р_С<Рч РїС_Р_С+РчС_С_С< ===============
error: create child process
Это ещё один очень интересный вопрос ... правда заслуживающий отдельной темы...
- редактировали ли вы мой файл?
- какой у вас используется редактор?
- в каком терминале вы выполняли .py программу?
- файл .py как и был, в UTF-8?
- стоит ли в .py файле вначале вот это? :

Код: Выделить всё

# -*- coding: utf-8 -*-

Аватара пользователя
Виктория
Писатель
Сообщения: 113
Зарегистрирован: 28 дек 2012, 14:05
Откуда: Самара
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Виктория » 07 авг 2013, 20:55

Olej, Ваш файл не редактировала. Запускала в far. Перенаправила вывод в файл, copypaste из редактора far (режим DOS). В режиме WIN "абрадакабра" другая.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Olej » 23 авг 2013, 16:04

Подсказали ;-) : интересная статья о параллелизме выполнения в Python - Parallel MapReduce in Python in Ten Minutes.
Использованием стандартного пакета (/usr/lib/python2.7) multiprocessing.

Из текста pydoc (http://localhost:8080/multiprocessing.html):
# This package is intended to duplicate the functionality (and much of
# the API) of threading.py but uses processes instead of threads. A
# subpackage 'multiprocessing.dummy' has the same API but is a simple
# wrapper for 'threading'.
#
Но с этим нужно отдельно разбираться...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Olej » 23 авг 2013, 16:19

Olej писал(а): Использованием стандартного пакета (/usr/lib/python2.7) multiprocessing.
Начиная вот с этого (файл num_proc.py):

Код: Выделить всё

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

from multiprocessing import cpu_count
print "число процессоров = %i" % cpu_count()
Как (и чем) они определяют число процессоров (ядер?) в системе?

Код: Выделить всё

bash-4.2$ cat /proc/cpuinfo | grep 'model name'
model name	: Genuine Intel(R) CPU           T2300  @ 1.66GHz
model name	: Genuine Intel(R) CPU           T2300  @ 1.66GHz
bash-4.2$ 
bash-4.2$ ./num_proc.py
число процессоров = 2
Здесь всё понятно...

... но (на совсем другом компьютере):

Код: Выделить всё

olej@atom:~/2013-WORK/python/multiprocessing$ python --version
Python 2.6.5
olej@atom:~/2013-WORK/python/multiprocessing$ ./num_proc.py 
число процессоров = 4
olej@atom:~/2013-WORK/python/multiprocessing$ cat /proc/cpuinfo | grep 'model name'
model name	: Intel(R) Atom(TM) CPU  330   @ 1.60GHz
model name	: Intel(R) Atom(TM) CPU  330   @ 1.60GHz
model name	: Intel(R) Atom(TM) CPU  330   @ 1.60GHz
model name	: Intel(R) Atom(TM) CPU  330   @ 1.60GHz
На процессорах Atom 4-х ядер не бывает (пока!?), но есть 2 ядра с hyperthreading ...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python - параллелизм

Непрочитанное сообщение Olej » 24 авг 2013, 15:47

Olej писал(а):Подсказали ;-) : интересная статья о параллелизме выполнения в Python - Parallel MapReduce in Python in Ten Minutes.
Использованием стандартного пакета (/usr/lib/python2.7) multiprocessing.
...
Но с этим нужно отдельно разбираться...
Очень любопытно!
Переделал (добавил + некоторые исправления) вот тот архив mthrs.tgz, который показывался и раньше...
Теперь это выглядит так (подробнее в архиве), т.е. значащих здесь всего 2 вызова:

Код: Выделить всё

def ncount( n ) : # тестовая CPU-загружающая функция
    while n > 0 : n -= 1
...
if 'm' in mode :
    print "=============== модуль multiprocessing =============="
    parms = []
    pool = multiprocessing.Pool( processes = thrnum, )
    for n in range( thrnum ) :
        parms.append( repnum )
    clc = time.time()
    pool.map( ncount, parms )
    clc = time.time() - clc
    print "время %5.2f секунд" % clc

Код: Выделить всё

bash-4.2$ python mthrs.py 
число процессоров (ядер) = 2
исполнение в Python версия 2.7.3 (default, Jul 24 2012, 10:05:39) 
число ветвей выполнения 2
число циклов в ветви 10000000
============ последовательное выполнение ============
время  2.89 секунд
================ параллельные потоки ================
время  3.44 секунд
=============== параллельные процессы ===============
время  1.74 секунд
=============== модуль multiprocessing ==============
время  1.81 секунд
Он ведёт аналогично как и fork() ... Теперь добавились "моды" (опция -m): значение m - multiprocessing, ... ну и те, что были раньше: s - последовательное выполнение, t - параллельные потоки, p - параллельные процессы ... это сделано чтобы можно было запустить только один тип (или несколько) выполнения, поскольку в некоторых ОС (Windows ;-) ) некоторые режимы принципиально слетают... ну и чтоб время при экспериментах не терять - можно делать так:

Код: Выделить всё

bash-4.2$ ./mthrs.py -n5000000 -mm
число процессоров (ядер) = 2
исполнение в Python версия 2.7.3 (default, Jul 24 2012, 10:05:39) 
число ветвей выполнения 2
число циклов в ветви 5000000
=============== модуль multiprocessing ==============
время  0.87 секунд
Некоторые вещи (совсем посторонние) достаточно странно выглядят... например, что выполнение практически того же самого кода (print не в счёт ;-) ) в Python 3 заметно (чуть ли не в 3 раза!) длиннее, чем в Python 2 - сравните:

Код: Выделить всё

bash-4.2$ python3 mthrs3.py 
число процессоров (ядер) = 2
исполнение в Python версия 3.2.3 (default, Jun  8 2012, 05:37:15) 
число ветвей выполнения 2
число циклов в ветви 10000000
============ последовательное выполнение ============
время 6.48 секунд
================ параллельные потоки ================
время 8.82 секунд
=============== параллельные процессы ===============
время 3.90 секунд
=============== модуль multiprocessing ==============
время 4.02 секунд
Вложения
mthrs.tgz
(8.47 КБ) 365 скачиваний

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 6 гостей