Ich habe ein kleines Programm geschrieben, welches in einem Modell für verteilten Speicher Verfügbarkeiten vorberechnen soll, damit dort wo es dann genutzt wird eine einfach Datenbankabfrage ausreicht. Dazu habe ich den line-profiler installiert, mir fällt aber gerade keine besonders tolle Möglichkeit zur Verbesserung ein. Habt ihr Tipps für die Optimierung? Meint ihr ich soll das ganze lieber in C schreiben?
Damit der Code zumindest etwas Sinn macht; Die Variable C zählt einfach die Verfügbarkeiten hoch. In dem Beispiel fange ich an mit 15 Speichern, die alle die Verfügbarkeit 0,5 haben. Statt mit Gleitkommazahlen zu rechnen nehme ich die Verfügbarkeit Mal 100, damit ich mit ganzzahligen Werten rechnen kann. Dann wird die Wahrscheinlichkeit berechnet, dass mindestens k Speicher auf einmal verfügbar sind.
Was natürlich noch möglich wäre ist das Programm mehrfach mit unterschiedlichen Werten zu starten, um das ganze "Mehrprozess fähig" zu machen und die Ergebnisse am Ende zusammenzufügen. Außerdem werden zur Zeit manche Wahrscheinlichkeiten noch zweimal berechnet (P([0,5;0,6;0,4])=P(0,6;0,4;0,5), die Wahrscheinlichkeiten sind gleich, da nur die Position der Wahrscheinlichkeiten vertauscht wurde).
Hier die Ausgabe:
Code: Alles auswählen
kernprof.py -lv availability.py
[...]
File: availability.py
Function: main at line 8
Total time: 43.5855 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
8 @profile
9 def main():
10 1 0 0.0 0.0 availabilities_dict = {}
11 1 0 0.0 0.0 C = 505050505050505050505050505050
12 100 0 0.0 0.0 for k in range(1,100):
13 99 0 0.0 0.0 availabilities_dict[k] = {}
14 3 0 0.0 0.0 while True:
15 3 0 0.0 0.0 C += 5
16 3 0 0.0 0.0 node_availabilities = C
17 3 0 0.0 0.0 availabilities_list = []
18 45 1000 22.2 0.0 while True:
19 45 0 0.0 0.0 availabilities_list.append(node_availabilities % 100)
20 45 0 0.0 0.0 node_availabilities /= 100
21 45 0 0.0 0.0 if node_availabilities == 0:
22 3 0 0.0 0.0 break
23 33 0 0.0 0.0 for k in range(1,len(availabilities_list)+1): # number of storage targets sufficient for object availability
24 31 1000 32.3 0.0 print "k:"+str(k)
25 31 0 0.0 0.0 result = 0 # availability
26 505376 1723110 3.4 4.0 for S in powerset(availabilities_list, k):
27 505346 639040 1.3 1.5 av = uv = 1
28 4516747 5866318 1.3 13.5 for a in S:
29 4011401 5777364 1.4 13.3 av *= a
30 505346 955055 1.9 2.2 unavailabilities_list = list(availabilities_list)
31 4516747 5864336 1.3 13.5 for e in S:
32 4011401 6135366 1.5 14.1 unavailabilities_list.remove(e)
33 7642909 10566572 1.4 24.2 for u in [100-u_b for u_b in unavailabilities_list]:
34 3568781 5230303 1.5 12.0 uv *= u
35 505345 825050 1.6 1.9 result += av * uv
36 30 1000 33.3 0.0 availabilities_dict[k][C] = 1.0*result/(pow(100,len(availabilities_list)))
Code: Alles auswählen
from itertools import *
from sys import exit
def powerset(some_list, minimal_number_of_elements):
'''Powerset of some_list, where some_list is a multiset'''
for subset in chain.from_iterable(combinations(some_list, r) for r in range(minimal_number_of_elements,len(some_list)+1)):
yield list(subset)
@profile
def main():
availabilities_dict = {}
C = 505050505050505050505050505050
for k in range(1,100):
availabilities_dict[k] = {}
while True:
C += 5
node_availabilities = C
availabilities_list = []
while True:
availabilities_list.append(node_availabilities % 100)
node_availabilities /= 100
if node_availabilities == 0:
break
for k in range(1,len(availabilities_list)+1): # number of storage targets sufficient for object availability
print "k:"+str(k)
result = 0 # availability
for S in powerset(availabilities_list, k):
av = uv = 1
for a in S:
av *= a
unavailabilities_list = list(availabilities_list)
for e in S:
unavailabilities_list.remove(e)
for u in [100-u_b for u_b in unavailabilities_list]:
uv *= u
result += av * uv
availabilities_dict[k][C] = 1.0*result/(pow(100,len(availabilities_list)))
if __name__ == "__main__":
main()