Python

Программные средства разработки

Модераторы: Olej, vikos

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

Re: Python

Непрочитанное сообщение Olej » 25 июн 2013, 12:37

Виктория писал(а):А чем может помочь простому программисту-труженику функциональное программирование? Изучив эту очередную парадигму, а автоматизации своего труда может и не научишься...
Вопрос хороший, уместный.

В принципе, на Python можно вполне писать код совершенно в стиле C++: классы есть? - есть, if-then-else есть? - есть, ... немножко другая (но похожая вомногом) библиотека встроенных функций + здоровенный набор функций в модулях (библиотека)...
Вполне возможно ... и имеет право быть.

Но только один и тот же код, эквивалентный, на Python будет по разным источниками раз в 40-100 медленнее, чем C ... а на C++ разницы с C нет, чтобы объектные альтернативы сравнивать.
И тогда рационально такой код записать всё-таки на C++.
(всё таки нужно платить быстродействием за интерпретацию ... пусть и не исходного кода, но компилированного байт-кода Python, в этом смысле близкая аналогия с Java)

Для Python декларируется быстрая разработка кода, нужно (там где уместно) использовать именно это его достоинство (пусть в 100 раз медленнее на исполнении, но зато в 5 раз быстрее код будет создан). А использовать это преимущество можно если пользовать те динамические возможности, гибкость периода исполнения, которые позволяют интерпретирующие языки. Иначе получится, что от эффкетивности реализации C++ мы отказались, а производительность разработки Python не использовали.

Для эффективного использования в кода на Python плодотворны те идеи и приёмы, которые тянутся из таких языков (из числа старых) как LISP, Forth, APL ... ну и нескольких новых языков последнего времени. Поэтому очень полезно представлять как такие приёмы выражаются средствами Python (потому что идеи идеями, но их ещё нужно и записать в предлагаемом синтаксисе).

Olej1
Администратор
Сообщения: 35
Зарегистрирован: 07 ноя 2012, 21:16
Контактная информация:

Re: Python

Непрочитанное сообщение Olej1 » 27 июн 2013, 22:26

Olej писал(а): 2. Заинтересовало меня:
Olej писал(а): глава функционального программирования
Помимо этого, есть несколько позиций в кодировании Python, которые любопытно бы проверить на примерах, и которые совершенно нужны дальше на практике...
И во всех описаниях Python (официальной документации на сайте, pdoc-системе, учебных курсах и книгах) эти несколько позиций очень неважно (по верхам, или очень невнятно) описаны.
Это вот какие вещи:

1. "ручное" написание (без swig и других полезных инструментов) модулей Python на C/C++;
2. обработка опций командной строки (модуль getopt) для построения консольных приложений UNIX-style;
3. реализация параллельных потоков (причём как в технике "низкого уровня" - модуль thread, так и технике "высокого уровня" - модуль threading) + какие доступны механизмы синхронизаций, потому как без синхронизации цена параллелизму - ноль.
4. работа с сигналами UNIX - модуль signal ... поклонники Windows могут на этот счёт не беспокоиться ;-) , но для UNIX это весьма существенно;

Что ещё забыл? ;-)

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

Re: Python

Непрочитанное сообщение Olej » 28 июн 2013, 00:27

Olej1 писал(а): 1. "ручное" написание (без swig и других полезных инструментов) модулей Python на C/C++;
Хочу написать функцию rdtsc() чтения аппаратного счётчика процессорных циклов (x86 начиная с Pentium 2).

- файл rdstc.c (это не только C, но ассемблер):

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

unsigned long long rdtsc( void ) {
   unsigned long long int x;
// asm volatile ( ".byte 0x0f, 0x31" : "=A" (x) ); // вариант для старых версий GCC
   asm volatile ( "rdtsc" : "=A" (x) );
   return x;
}
- файл общих определений (не сильно нужен):

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

extern unsigned long long rdtsc( void );

- файл-врапер (rdtsc_wrap.c - имя произвольное) для Python :

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

// модуль "rdtsc":
#include <Python.h>
#include "rdtsc.h"

PyObject* rdtsc_wrap( PyObject* self, PyObject* args ) {
   if( self != NULL ) return NULL;
   return Py_BuildValue( "L", rdtsc() );
}

// таблица методов
static PyMethodDef rdtscmethods[] = {
   { "rdtsc", rdtsc_wrap, METH_NOARGS },
   { NULL, NULL }
};

// функция инициализации модуля
void initrdtsc() {
   Py_InitModule( "rdtsc", rdtscmethods );
}
Всё. Можно писать Makefile :

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

TITLE = rdtsc

all:    $(TITLE).c $(TITLE)_wrap.c
        gcc -c -fpic $(TITLE)_wrap.c $(TITLE).c -I/usr/include/python2.7
        ld -shared $(TITLE)_wrap.o $(TITLE).o -lc -o $(TITLE)module.so
        rm -f *.o

clean:
        rm -f $(TITLE)module.so $(TITLE)_wrap.o $(TITLE).o *.pyc *.pyo

test:   $(TITLE)module.so ctest.c $(TITLE).h
        gcc ctest.c $(TITLE).c -o ctest
        ./ctest
        python -O ptest.py

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

Re: Python

Непрочитанное сообщение Olej » 28 июн 2013, 00:49

Olej писал(а):Всё. Можно писать Makefile :
make собирает библиотеку rdtscmodule.so, которая и есть реализацией модуля rdtsc в терминологии Python.
Там же, в Makefile, собираются 2 теста (тест C и тест Python)...
- ctest.c

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

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "rdtsc.h"

#define NUMB 10
static unsigned calibr( int rep ) {
   uint32_t n, m, sum = 0;
   n = m = ( rep <= 0 ? NUMB : rep );
   while( n-- ) {
      uint64_t cf, cs;
      cf = rdtsc();
      cs = rdtsc();
      sum += (uint32_t)( cs - cf );
   }
   return sum / m;
}

int main( int argc, char **argv, char **envp ) {
   printf( "число процессорных тактов = %llu\n", rdtsc() );
   printf( "калибровка последовательных вызовов:" );
   printf( " %lu(0)", calibr( 0 ) );
   int n;
   for( n = 10; n <= 100000; n*=10 )
      printf( " %lu(%d)", calibr( n ), n );
   printf( "\n");
   exit( EXIT_SUCCESS );
};

- pytest.py

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

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

from rdtsc import rdtsc
from calibr import calibr

counter = []
for i in range( 5 ):
    counter.append( rdtsc() )
print "счётчик процессорных циклов:\n", counter

arg = [ 0, 10, 100, 1000, 10000, 100000 ]
msg = "калибровка последовательных вызовов:"
for i in arg:
    s = " %s(%i)" % ( str( calibr( i ) ), i )
    msg = msg + s
print msg
- модуль Pyton, который требуется pytest.py, файл calibr.py

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

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

from rdtsc import rdtsc

def calibr( args = 10 ):
    sum = 0L
    if int( args ) <= 0: n = 10
    else: n = int( args )
    m = n
    while( n > 0 ):
        cf = -( rdtsc() - rdtsc() )
        sum = sum + cf
        n = n - 1
    return sum / m
Проверяемся (вызывается C тест, затем сразу аналог Python):

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

bash-4.2$ make test
gcc ctest.c rdtsc.c -o ctest
./ctest
число процессорных тактов = 79971042747980
калибровка последовательных вызовов: 117(0) 115(10) 115(100) 147(1000) 139(10000) 115(100000)
python -O ptest.py
счётчик процессорных циклов:
[79971137334370L, 79971137337650L, 79971137338900L, 79971137340040L, 79971137341090L]
калибровка последовательных вызовов: 548(0) 515(10) 947(100) 500(1000) 487(10000) 484(100000)
Всё ОК. Python тест раз в 4-5 помедленнее будет C-шного ... но это нормально.

Относительно изготовления высокопроизводительных модулей под Python на C можно считать, что всё ОК.
Всё достаточно хорошо описано в документации (Extending Python with C or C++).
Кроме того, для этого есть такой приличный инструмент как Swig.

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

Re: Python

Непрочитанное сообщение Olej » 28 июн 2013, 00:59

Olej писал(а): Хочу написать функцию rdtsc() чтения аппаратного счётчика процессорных циклов (x86 начиная с Pentium 2).
Теперь, с таким имеющимся инструментом измерения временных интервалов с наносекундной точностью, можно подходить и к следующим вопросам:
Olej1 писал(а): 2. обработка опций командной строки (модуль getopt) для построения консольных приложений UNIX-style;
3. реализация параллельных потоков (причём как в технике "низкого уровня" - модуль thread, так и технике "высокого уровня" - модуль threading) + какие доступны механизмы синхронизаций, потому как без синхронизации цена параллелизму - ноль.

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

Re: Python

Непрочитанное сообщение Olej » 28 июн 2013, 01:19

Olej писал(а): Теперь, с таким имеющимся инструментом измерения временных интервалов с наносекундной точностью, можно подходить и к следующим вопросам:
Olej1 писал(а): 2. обработка опций командной строки (модуль getopt) для построения консольных приложений UNIX-style;
3. реализация параллельных потоков (причём как в технике "низкого уровня" - модуль thread, так и технике "высокого уровня" - модуль threading) + какие доступны механизмы синхронизаций, потому как без синхронизации цена параллелизму - ноль.
1. реализация "низкого уровня" - модуль thread; крайне скудно описан в документации и литературе; там очень скудные возможности синхронизации - один единственный примитив (LockType = class lock), что-то на манер самого простейшего бинарного мютекса; для того, чтобы дождаться окончания дочерних потоков ("барьер") нужно сгородить искусственную конструкци. на манер контейнера barier - типа счётного семафора:

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

bash-4.2$ cat tlspeed.py 
#!/usr/bin/python -O
# -*- coding: utf-8 -*-

from rdtsc import rdtsc
from calibr import calibr
import getopt
import sys
import thread
import time
import string

debuglevel = 0
threadnum = 2
delay = 1
numt = 0                      # текущее число активных дочерних потоков
lock = thread.allocate_lock() # блокировка доступа к числу активных дочерних потоков
wait = thread.allocate_lock() # блокировка ожидания завершения всех дочерних потоков
barier = { 'numt' : numt, 'lock' : lock, 'wait' : wait }

def thrfun( delay, num, tstart ):
    st = rdtsc() - tstart
    barier[ 'numt' ] = barier[ 'numt' ] + 1  
    barier[ 'lock' ].release()
    ss = "\t%i : %i <= старт: %u" % ( num, id, st )
    time.sleep( delay ) 
    barier[ 'lock' ].acquire()
    barier[ 'numt' ] = barier[ 'numt' ] - 1 
    st = rdtsc() - tstart
    print "%s - финиш: %u" % ( ss, st )
    if 0 == barier[ 'numt' ] :
        barier[ 'wait' ].release()
    barier[ 'lock' ].release()
    return

#opts, args = getopt.getopt( sys.argv[1:], "vt:", ['`exclude='] )
opts, args = getopt.getopt( sys.argv[1:], "vt:d:" )
for opt, arg in opts: # опции (ключи) командной строки (-t, -v)
#    print opt, arg
    if 0 == cmp( opt[ 1: ], 'v' ): debuglevel = debuglevel + 1
    elif 0 == cmp( opt[ 1: ], 't' ): threadnum = string.atoi( arg )
    elif 0 == cmp( opt[ 1: ], 'd' ): delay = string.atoi( arg )
if debuglevel > 0 :
    print opts
    print args
    print  debuglevel
    print  threadnum

barier[ 'wait' ].acquire()   # захват блокировки завершения
for n in range( threadnum ):# запуск threadnum потоков
    barier[ 'lock' ].acquire()
    id = thread.start_new_thread( thrfun, ( delay, n, rdtsc() ) )
    print "\t%i : %i =>" % ( n, id )

barier[ 'wait' ].acquire()  # ожидание завершения всех потоков
print "завершены все %i потоков, завершается ожидавший главный поток" % threadnum
2. реализация "высокого уровня" - модуль threading; здесь всё гораздо проще (но в кое-чём и сложнее ... например передаче параметров в потоковую функцию), но здесь уже много разных примитивов синхронизации (Lock, RLock, Condition, Semaphore, Event, Queue); эквивалентный предыдущему пример:

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

bash-4.2$ cat thspeed.py 
#!/usr/bin/python -O
# -*- coding: utf-8 -*-

from rdtsc import rdtsc
from calibr import calibr
import getopt
import sys
import threading
import time
import string

debuglevel = 0
threadnum = 2
delay = 1

def thrfun( *args ):   
    st = rdtsc() - args[ 2 ] # время старта потока
    ss = "\t%i : %s <= старт: %u" % \
         ( args[ 1 ], threading.currentThread().getName(), st )
    time.sleep( args[ 0 ] )  # пауза 
    st = rdtsc() - args[ 2 ] # время завершения потока 
    print "%s - финиш: %u" % ( ss, st )
    return

opts, args = getopt.getopt( sys.argv[1:], "vt:d:" )
for opt, arg in opts: # опции (ключи) командной строки (-t, -v)
#    print opt, arg
    if 0 == cmp( opt[ 1: ], 'v' ): debuglevel = debuglevel + 1
    elif 0 == cmp( opt[ 1: ], 't' ): threadnum = string.atoi( arg )
    elif 0 == cmp( opt[ 1: ], 'd' ): delay = string.atoi( arg )
if debuglevel > 0 :
    print opts
    print args
    print  debuglevel
    print  threadnum

threads = []
for n in range( threadnum ): # создание и запуск потоков
    parm = [ delay, n, 0 ]
    t = threading.Thread( target=thrfun, args=parm )
    threads.append( t )
    t.setDaemon( 1 )
    print "\t%i : %s =>" % ( n, t.getName() )
    parm[ 2 ] = rdtsc()
    t.start()

for n in range( threadnum ): # ожидание завершения всех потоков
    threads[ n ].join()

print "завершены все %i потоков, завершается ожидавший главный поток" % threadnum
Результаты прогонов обоих вариантов (и getopt обработка ключей команды заодно):

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

bash-4.2$ ./tlspeed.py  -t3 -d3
        0 : -1219589312 =>
        1 : -1229980864 =>
        2 : -1240466624 =>
        0 : -1219589312 <= старт: 316450 - финиш: 4993234920
        2 : -1240466624 <= старт: 235850 - финиш: 4992812200
        1 : -1229980864 <= старт: 162580 - финиш: 4993124550
завершены все 3 потоков, завершается ожидавший главный поток

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

bash-4.2$ ./thspeed.py  -t3 -d3
        0 : Thread-1 =>
        1 : Thread-2 =>
        2 : Thread-3 =>
        0 : Thread-1 <= старт: 297480 - финиш: 4992905670
        1 : Thread-2 <= старт: 177510 - финиш: 4992776540
        2 : Thread-3 <= старт: 302600 - финиш: 4992569960
завершены все 3 потоков, завершается ожидавший главный поток
Если кому будет проверить всё это, то вот прилагается архивчик, где всё это есть...
Вложения
pytspeed.tgz
(7.69 КБ) 427 скачиваний

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

Re: Python

Непрочитанное сообщение Olej » 28 июн 2013, 09:53

Olej писал(а): Результаты прогонов обоих вариантов (и getopt обработка ключей команды заодно):
Тут важнейший вопрос: является ли сам интерпретатор, исполнитель байт-кода Python многопоточным? т.е. исполняет ли он многопоточный байт-код на всех доступных ядрах-процессорах, или только квазипараллельно на одном том, на котором сам исполняется?

Нигде в описаниях и обсуждениях я ответа на этот вопрос не нашёл. В одном из лучших источников - Дэвид М. Бизли "Язык программирования Python. Справочник":
Планирование нитей и переключение нитей жестко контролируется глобальной блокировкой интерпретатора, которая допускает функционирование в интерпретаторе одновременно только одной нити выполнения. Кроме того, переключение нитей может происходить лишь в промежутке между выполнением в интерпретаторе отдельных байт-кодов.
Но это написано относительно Python версии 1.5

Для проверки пришлось добавить к программам-тестам опцию -a, когда задержка выполняется не как time.sleep(), а как тупое выполнение в цикле ненужной работы на протяжении заказанной паузы:

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

def delay_in_cycle( delay = 1 ):
    t = time.time()
    while time.time() - t < delay :
        time.localtime()
И вот что в итоге имеем:

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

bash-4.2$ ./thspeed.py -t5 -a -d5
	0 : Thread-1 =>
	1 : Thread-2 =>
	2 : Thread-3 =>
	3 : Thread-4 =>
	4 : Thread-5 =>
	0 : Thread-1 <= старт: 491740 - финиш: 8312995010
	1 : Thread-2 <= старт: 94473100 - финиш: 8426496550
 	2 : Thread-3 <= старт: 13304070 - финиш: 8325757430
	3 : Thread-4 <= старт: 19977290 - финиш: 8348894870
	4 : Thread-5 <= старт: 42896730 - финиш: 8355479370
завершены все 5 потоков, завершается ожидавший главный поток
монитор_017.png
монитор_017.png (68.98 КБ) 6857 просмотров
Так что похоже, что вот тот 5-секундный "горб" (между 10-й и 20-й секундами) на картинке отрабатывают оба (в моём случае) процессора.
Вложения
pytspeed.tgz
(7.88 КБ) 426 скачиваний

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

Re: Python

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

Olej писал(а): Результаты прогонов обоих вариантов (и getopt обработка ключей команды заодно):
В той же манере, но запуск параллельных процессов UNIX - всё простенько и со вкусом ;-) :

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

bash-4.2$ cat fork.py 
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import time
import sys
import getopt
from rdtsc import rdtsc

delay = 1
procnum = 2
debuglevel = 0

opts, args = getopt.getopt( sys.argv[1:], "p:d:v" )
for opt, arg in opts: # опции (ключи) командной строки 
#    print opt, arg
    if 0 == cmp( opt[ 1: ], 'p' ): procnum = int( arg )
    if 0 == cmp( opt[ 1: ], 'd' ): delay = int( arg )
    if 0 == cmp( opt[ 1: ], 'v' ): debuglevel = debuglevel + 1

childs = []
if debuglevel : print "родительский процесс %i" % os.getpid()

for i in range( 0, procnum ) :
    tim = rdtsc();
    try :
        pid = os.fork();
    except :
        print "error: create child process"
        sys.exit( 33 )
    if pid == 0 :
        trun = rdtsc() - tim;
        if debuglevel : \
           print "дочерний процесс %i - циклов процессора на запуск: %u" % \
           ( os.getpid(), trun );
        time.sleep( delay )
        trun = rdtsc() - tim;
        if debuglevel : \
           print "дочерний процесс %i - время завершения: %u" % \
           ( os.getpid(), trun );
        sys.exit( 3 )
    if pid > 0 :
        childs.append( pid )
        if debuglevel : print "%i: создан новый дочерний процесс %i" % ( os.getpid(), pid )


print "ожидание завершения дочерних процессов ..."
for p in childs :
    pid, status = os.wait()
    if debuglevel : print "код завершения процесса %i = %i" % ( pid, os.WEXITSTATUS( status ) )

print "все порождённые процессы успешно завершены"

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

bash-4.2$ ./fork.py -p3 -d2 -v
родительский процесс 17743
17743: создан новый дочерний процесс 17744
17743: создан новый дочерний процесс 17745
17743: создан новый дочерний процесс 17746
ожидание завершения дочерних процессов ...
дочерний процесс 17746 - циклов процессора на запуск: 1136190
дочерний процесс 17745 - циклов процессора на запуск: 2535930
дочерний процесс 17744 - циклов процессора на запуск: 4064020
дочерний процесс 17746 - время завершения: 3330095370
дочерний процесс 17745 - время завершения: 3334456990
дочерний процесс 17744 - время завершения: 3342243510
код завершения процесса 17746 = 3
код завершения процесса 17745 = 3
код завершения процесса 17744 = 3
все порождённые процессы успешно завершены

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

bash-4.2$ ./fork.py -p100
ожидание завершения дочерних процессов ...
все порождённые процессы успешно завершены
bash-4.2$ ./fork.py -p500
ожидание завершения дочерних процессов ...
все порождённые процессы успешно завершены
bash-4.2$ ./fork.py -p721
ожидание завершения дочерних процессов ...
все порождённые процессы успешно завершены
bash-4.2$ echo $?
0
bash-4.2$ ./fork.py -p722
error: create child process
bash-4.2$ echo $?
33
Что здесь интересно?: что временные затраты (число процессорных циклов) на запуск процесса или потока для исполняющей системы Python - практически одного порядка, основное время съедает интерпретирующая система, а не выполнение системных вызовов POSIX.

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

Re: Python

Непрочитанное сообщение Olej » 26 июл 2013, 00:39

Olej писал(а): 1. Книга: Г. Россум, Ф.Л.Дж. Дрейк, Д.С. Откидач "Язык программирования Python".
Это не перевод (не совсем перевод) - переводчиком сделана большая адаптация и проверка примеров кода...

Книга не новая, 2000-2001г.г., но по детальности многих описания (например, пространства имён, организация и импорт модулей и пакетов и др.) - превосходит большинство последних ... а основные принципы Photon за это время не изменились...

P.S. Эта же книга есть здесь на этом сайте, но она здесь в формате PDF, менее удобном для изучения.

2. А здесь: ActiveState Code - много-много десятков образцов кода на Python.
Ещё один очень приличного уровня ресурс - весьма свежие и профессиональные переводы книг из комплекта документации Pyhton:
http://ru.wikibooks.org/wiki/Документация_Python
http://ru.wikibooks.org/wiki/Учебник_Python_3.1
http://ru.wikibooks.org/wiki/Справочник ... Python_3.1
И другие переводы (в рабочей стадии) там же, или там указаны их URL.

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

Re: Python

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

Olej писал(а): Тут важнейший вопрос: является ли сам интерпретатор, исполнитель байт-кода Python многопоточным? т.е. исполняет ли он многопоточный байт-код на всех доступных ядрах-процессорах, или только квазипараллельно на одном том, на котором сам исполняется?

Нигде в описаниях и обсуждениях я ответа на этот вопрос не нашёл. В одном из лучших источников - Дэвид М. Бизли "Язык программирования Python. Справочник":
Вот перевод такой ужасной статьи David Beazley Как устроен GIL в Python:
18 февраля 2010 в 12:29
Как устроен GIL в Python
Это относительно реализации потоков в Python, глобальной блокировки GIL ((Global Interpreter Lock), и выполнение на многопроцессорных (многоядерных) системах.

В которой утверждается и объясняется:
Следующие результаты получены на двухъядерном MacBook:
последовательный запуск — 24,6 с
параллельный запуск — 45,5 с (почти в 2 раза медленнее!)
параллельный запуск после отключения одного из ядер — 38,0 с
Т.е. что выполнение в несколько потоков на многоядерном компьютере может быть медленнее, чем на одном ядре (на одном процессоре)!

Это написано 02.2010 (я специально сохранил дату) ... какая тогда была версия Python?
Где-то говорилось, что в версии Python 3.2 в реализации GIL что-то радикально поменяли ... или нет?
Нужно это обязательно проверить на последних версиях, что там происходит!

Ответить

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

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

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