Optimiertes Skalarprodukt in Python

Das Skalarprodukt zweier n-dimensionaler Vektorenu=[u1,u2,...un] undv=[v1,v2,...,vn] ist gegeben durchu1*v1 + u2*v2 + ... + un*vn.

Eine Fragegestern gepostet Ich ermutigte mich, den schnellsten Weg zu finden, um Punktprodukte in Python zu berechnen, indem ich nur die Standardbibliothek, keine Module von Drittanbietern oder C / Fortran / C ++ - Aufrufe verwende.

Ich habe vier verschiedene Ansätze geplant; bisher scheint das am schnellsten zu seinsum(starmap(mul,izip(v1,v2))) (woherstarmap undizip kommen aus demitertools Modul).

Für den unten dargestellten Code sind dies die abgelaufenen Zeiten (in Sekunden für eine Million Durchläufe):

d0: 12.01215
d1: 11.76151
d2: 12.54092
d3: 09.58523

Können Sie sich einen schnelleren Weg vorstellen, dies zu tun?

import timeit # module with timing subroutines                                                              
import random # module to generate random numnbers                                                          
from itertools import imap,starmap,izip
from operator import mul

def v(N=50,min=-10,max=10):
    """Generates a random vector (in an array) of dimension N; the                                          
    values are integers in the range [min,max]."""
    out = []
    for k in range(N):
        out.append(random.randint(min,max))
    return out

def check(v1,v2):
    if len(v1)!=len(v2):
        raise ValueError,"the lenght of both arrays must be the same"
    pass

def d0(v1,v2):
    """                                                                                                     
    d0 is Nominal approach:                                                                                 
    multiply/add in a loop                                                                                  
    """
    check(v1,v2)
    out = 0
    for k in range(len(v1)):
        out += v1[k] * v2[k]
    return out

def d1(v1,v2):
    """                                                                                                     
    d1 uses an imap (from itertools)                                                                        
    """
    check(v1,v2)
    return sum(imap(mul,v1,v2))

def d2(v1,v2):
    """                                                                                                     
    d2 uses a conventional map                                                                              
    """
    check(v1,v2)
    return sum(map(mul,v1,v2))

def d3(v1,v2):
    """                                                                                                     
    d3 uses a starmap (itertools) to apply the mul operator on an izipped (v1,v2)                           
    """
    check(v1,v2)
    return sum(starmap(mul,izip(v1,v2)))

# generate the test vectors                                                                                 
v1 = v()
v2 = v()

if __name__ == '__main__':

    # Generate two test vectors of dimension N                                                              

    t0 = timeit.Timer("d0(v1,v2)","from dot_product import d0,v1,v2")
    t1 = timeit.Timer("d1(v1,v2)","from dot_product import d1,v1,v2")
    t2 = timeit.Timer("d2(v1,v2)","from dot_product import d2,v1,v2")
    t3 = timeit.Timer("d3(v1,v2)","from dot_product import d3,v1,v2")

    print "d0 elapsed: ", t0.timeit()
    print "d1 elapsed: ", t1.timeit()
    print "d2 elapsed: ", t2.timeit()
    print "d3 elapsed: ", t3.timeit()

Beachten Sie, dass der Name der Datei sein mussdot_product.py damit das Skript ausgeführt wird; Ich habe Python 2.5.1 unter Mac OS X Version 10.5.8 verwendet.

BEARBEITEN:

Ich habe das Skript für N = 1000 ausgeführt und dies sind die Ergebnisse (in Sekunden für eine Million Durchläufe):

d0: 205.35457
d1: 208.13006
d2: 230.07463
d3: 155.29670

Ich denke, es ist sicher anzunehmen, dass Option drei die schnellste und Option zwei die langsamste (von den vier vorgestellten) ist.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage