Code: Alles auswählen
>>> a = ((2,3,4),(3,4,5),(4,5,6))
>>> map(sum, a)
<map object at 0x0000000003123A58>
>>> for b in map(sum,a):
print(b)
9
12
15
>>>
Code: Alles auswählen
>>> a = ((2,3,4),(3,4,5),(4,5,6))
>>> map(sum, a)
<map object at 0x0000000003123A58>
>>> for b in map(sum,a):
print(b)
9
12
15
>>>
Ja und? Hier rufst Du ja auch eine Funktion auf und nicht das Tupel! Ich kapiere den Einwand jetzt irgend wie nicht...heiliga horsd hat geschrieben: Da hab ich ja auch eine Funktion und ein Tupel das ich übergebe und es funktioniert?
Code: Alles auswählen
def check_combinations(combinations_to_check):
for combination in combinations_to_check():
...
Code: Alles auswählen
result = pool.map(check_combinations, give_combinations(), CHUNKSIZE)
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\XX\Desktop\Lotto.py", line 43, in <module>
print(find_combination())
File "C:\Users\XX\Desktop\Lotto.py", line 38, in find_combination
result = pool.map(check_combinations, give_combinations(), CHUNKSIZE)
File "C:\Python32\lib\multiprocessing\pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "C:\Python32\lib\multiprocessing\pool.py", line 556, in get
raise self._value
TypeError: 'int' object is not iterable
Code: Alles auswählen
from itertools import combinations
import operator
import collections
try:
from functools import reduce
except ImportError:
pass
try:
from itertools import imap
except ImportError:
imap = map
DIFFERENT_VALUES = 49
NUMBERS = list(range(1,DIFFERENT_VALUES + 1))
MIN_VALUE = 2*10**6
VALUES_TO_COMBINE = 6
PROCESSES = 14
CHUNKSIZE = 10**6
sums = None # Um 'global' herumgemogelt
def product(iterable):
return reduce(operator.mul, iterable, 1)
def give_combinations():
return combinations(NUMBERS, 6)
def check_combinations(combinations_to_check):
for combination in combinations_to_check:
sum_of_numbers = sum(combination)
x = sum_of_numbers * sums[sum_of_numbers]
if x > MIN_VALUE and product(combination) == x:
return(combination)
def find_combination():
pool = Pool(processes=PROCESSES)
sums = collections.Counter(imap(sum, give_combinations()))
result = pool.map(check_combinations, give_combinations(), CHUNKSIZE)
return result
if __name__ == "__main__":
print(find_combination())
Code: Alles auswählen
Traceback (most recent call last):
File "./combi.py", line 44, in <module>
print(find_combination())
File "./combi.py", line 38, in find_combination
pool = Pool(processes=PROCESSES)
NameError: global name 'Pool' is not defined
Code: Alles auswählen
from multiprocessing import Pool
Code: Alles auswählen
#!/usr/bin/env python
from operator import add
from itertools import imap
reduce(add, [1, 2, 3])
imap(lambda x: x+1, [1, 2, 3])
Code: Alles auswählen
1 nelson@destiny ~/src/Python/forum/combinations % 2to3 test.py
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored test.py
--- test.py (original)
+++ test.py (refactored)
@@ -1,8 +1,9 @@
#!/usr/bin/env python
from operator import add
-from itertools import imap
+from functools import reduce
+
reduce(add, [1, 2, 3])
-imap(lambda x: x+1, [1, 2, 3])
+map(lambda x: x+1, [1, 2, 3])
RefactoringTool: Files that need to be modified:
RefactoringTool: test.py
Code: Alles auswählen
sums = None # Um 'global' herumgemogelt
Code: Alles auswählen
In [146]: sum(42)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/bj/<ipython console> in <module>()
TypeError: 'int' object is not iterable
Code: Alles auswählen
from multiprocessing import Pool
from itertools import combinations
import operator
import collections
from functools import reduce
try:
from itertools import imap
except ImportError:
imap = map
DIFFERENT_VALUES = 49
NUMBERS = list(range(1,DIFFERENT_VALUES + 1))
MIN_VALUE = 2*10**6
PROCESSES = 14
CHUNKSIZE = 10**6
def product(iterable):
return reduce(operator.mul, iterable, 1)
def give_combinations():
return combinations(NUMBERS, 6)
def check_combinations(combination, sums):
sum_of_numbers = sum(combination)
x = sum_of_numbers * sums[sum_of_numbers]
if x > MIN_VALUE and product(combination) == x:
return combination
def find_combination():
#pool = Pool(processes=PROCESSES)
sums = collections.Counter(imap(sum, give_combinations()))
result = map(check_combinations, give_combinations(), CHUNKSIZE)
return result
if __name__ == "__main__":
print(find_combination())
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\XX\Desktop\Lotto.py", line 39, in <module>
print(find_combination())
File "C:\Users\XX\Desktop\Lotto.py", line 35, in find_combination
result = map(check_combinations, give_combinations(), CHUNKSIZE)
TypeError: 'int' object is not iterable
Dann überlege doch noch einmal, was CHUNKSIZE genau istheiliga horsd hat geschrieben:Jetzt iteriere ich doch nichtmehr über einen Integer, oder? Map übergibt die einzelnen Elemente des Kombination-Aufrufs an check_combinations - und das sind Tupel und keine Integer?
Mittels ``functools.partial``heiliga horsd hat geschrieben:Und wie bekomme ich - wenn nicht irgendwie über eine globale Variable - sums in den Namensraum von check_combinations?
Code: Alles auswählen
functools.partial(check_combinations, sums=sums)
Code: Alles auswählen
Traceback (most recent call last):
File "./combi2.py", line 38, in <module>
print(find_combination())
File "./combi2.py", line 34, in find_combination
result = map(check_combinations, give_combinations(), CHUNKSIZE)
TypeError: argument 3 to map() must support iteration
Code: Alles auswählen
def check_combinations(combination, sums=None):
...
result = map(partial(check_combinations, sums=sums), give_combinations())
Ich möchte ja nichts sagen, aber die erst Antwort in diesem Thread lautet:Hyperion hat geschrieben:Du verwendest also Python3, ich habe es mit Python2 getestet! Dann schreibe den Code doch auch entsprechend, damit das hier nicht zu einer Ratestunde wird
Hyperion hat geschrieben:Das hat nichts mit Python3 zu tun, sondern liegt am Verhalten von Generatoren!
Code: Alles auswählen
try:
from functools import reduce
except ImportError:
pass
try:
from itertools import imap
except ImportError:
imap = map
Code: Alles auswählen
from multiprocessing import Pool
from itertools import combinations
import operator
import collections
from functools import reduce, partial
try:
from itertools import imap
except ImportError:
imap = map
DIFFERENT_VALUES = 49
NUMBERS = list(range(1,DIFFERENT_VALUES + 1))
MIN_VALUE = 2*10**6
PROCESSES = 7
CHUNKSIZE = 2*10**6
def product(iterable):
return reduce(operator.mul, iterable, 1)
def give_combinations():
return combinations(NUMBERS, 6)
def check_combinations(combination, sums = None):
sum_of_numbers = sum(combination)
x = sum_of_numbers * sums[sum_of_numbers]
if x > MIN_VALUE and product(combination) == x:
return combination
def find_combination():
pool = Pool(processes=PROCESSES)
sums = collections.Counter(imap(sum, give_combinations()))
result = pool.map(partial(check_combinations, sums=sums),give_combinations(),
chunksize=CHUNKSIZE)
return result
if __name__ == "__main__":
for element in set(find_combination()): #Set um die ~14M None's los zu werden
print(element)
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from collections import defaultdict
from itertools import combinations
from operator import mul
def product(iterable):
return reduce(mul, iterable, 1)
def lotto_combinations(n=49, m=6):
return combinations(xrange(1, n + 1), m)
def main():
sum2count = defaultdict(list)
for combination in lotto_combinations():
sum2count[sum(combination)].append(combination)
for the_sum, combinations in sum2count.iteritems():
x = the_sum * len(combinations)
if x >= 2000000:
for combination in combinations:
if product(combination) == x:
print combination
if __name__ == '__main__':
main()
Code: Alles auswählen
Filename Impl. Runtime Factor
============== ====== ========= ===========
lotto_02.py python 6m41.216s -7.24
lotto_01.py python 34.144s 1.00
lotto_02.py pypy 21.054s 1.62
lotto_01.py pypy 11.635s 2.93
lotto_01.c 0.267s 127.88
Naja bin ehrlich gesagt noch nicht dazu gekommen deinem Hinweis nachzugehen. Wobei ich mich frage, ob die None's nicht Referenz auf ein einziges Objekt sind - Man bräuchte ja nicht mehr als ein None-Objekt im Speicher oder? Und Referenzen auf ein Objekt machen das Ding dann ja auch nicht so fett.BlackJack hat geschrieben:@heiliga horsd: Das ist IMHO eine unsinnige Vorgehensweise. Bei dem `Pool.map()` wird für iterierbare Objekte die keine abfragbare Länge haben erst einmal eine Liste mit allen Elementen erstellt. Ist zumindest in der Implementierung in Python 2.6 so. An der Stelle hat man im Grunde schon „verloren”. Und dann werden nicht nur ≈14 Millionen Kombinationen an die Prozesse übertragen, sondern auch ≈14 Millionen Ergebnisse, die alle bis auf *einen* Wert `None` sind. Das ist eine unglaubliche Verschwendung. Die ganzen Kombinationen werden auch nur in *einem* Prozess erzeugt, statt dass das auch Parallel passiert.
Wenn ich mal Zeit finde arbeite ich mich da auch mal ein - wobei hier eine Frage meinerseits wäre, wie ich so einem Generator mitteile, wann er aufhören muss und gleichzeitig schon Generator 2 mitteilen kann, wo er starten muss, bevor Generator 1 fertig ist.BlackJack hat geschrieben: Wie gesagt: Man braucht einen eigenen Kombinations-Generator der auch mitten drin „aufsetzen” kann, wenn man das vernünftig parallelisieren möchte. Dann kann man auch den ersten Schritt mit dem Histogramm in Teilhistogramme aufteilen die im Hauptprozess zusammengeführt werden.
Ja, das bei einem AMD FX-4100 (Quad Core, 3.6GHZ). Richtig bitter die Laufzeit...BlackJack hat geschrieben: Parallel 35s? Solange braucht bei mir die ganz normale Version mit den beiden Schleifen über alle Kombination. Und ich dachte ich hätte hier einen lahmen Rechner.
Ich würd's jetzt einfach bei dieser Variante belassen. Ich glaub, die scheint das beste zu sein, das man Performance-mäßig mit Python hinkriegen kann...heiliga horsd hat geschrieben:Hab jetzt auch mal diese Lösung:
http://www.python-forum.de/viewtopic.ph ... 29#p223629
in PyPy rein gefüttert, war nach 4 Sekunden durch.