2017-05-08 7 views
3

Ich versuche, das Punktprodukt von einer Matrix 331x23152 und 23152x23152 zu nehmen.Langsames Punktprodukt in R

In Python und Octave ist dies eine triviale Operation, aber in R scheint dies unglaublich langsam zu sein.

N <- 331 
M <- 23152 

mat_1 = matrix(rnorm(N*M,mean=0,sd=1), N, M) 
mat_2 = matrix(rnorm(N*M,mean=0,sd=1), M, M) 
tm3 <- system.time({ 
    mat_3 = mat_1%*%mat_2 
}) 
print(tm3) 

Der Ausgang ist

user system elapsed 
101.95 0.04 101.99 

Mit anderen Worten, dieses Punktprodukt über 100 Sekunden dauert auszuführen.

Ich benutze R-3.4.0 64-bit, mit RStudio v1.0.143 auf einem i7-4790 mit 16 GB RAM. Daher habe ich nicht erwartet, dass diese Operation so lange dauert.

Habe ich etwas übersehen? Ich habe angefangen, die Pakete bigmemory und bigalgebra zu betrachten, aber ich kann nicht anders, als zu denken, dass es eine Lösung gibt, ohne auf Pakete zurückgreifen zu müssen.


EDIT

Um Ihnen eine Vorstellung von Zeitdifferenz, hier ist ein Skript für Octave:

n = 331; 
m = 23152; 

mat_1 = rand(n,m); 
mat_2 = rand(m,m); 
tic 
mat_3 = mat_1*mat_2; 
toc 

Der Ausgang ist

Elapsed time is 3.81038 seconds. 

Und in Python:

import numpy as np 
import time 

n = 331 
m = 23152 

mat_1 = np.random.random((n,m)) 
mat_2 = np.random.random((m,m)) 
tm_1 = time.time() 
mat_3 = np.dot(mat_1,mat_2) 
tm_2 = time.time() 
tm_3 = tm_2 - tm_1 
print(tm_3) 

Der Ausgang ist

2.781277894973755 

Wie Sie sehen können, diese Zahlen sind nicht einmal in derselben Liga.

EDIT 2

Bei Zheyuan Li Anfrage sind hier Spielzeug Beispiele für Punktprodukte.

In R:

mat_1 = matrix(c(1,2,1,2,1,2), nrow = 2, ncol = 3) 
mat_2 = matrix(c(1,1,1,2,2,2,3,3,3), nrow = 3, ncol = 3) 
mat_3 = mat_1 %*% mat_2 
print(mat_3) 

Der Ausgang ist:

 [,1] [,2] [,3] 
[1,] 3 6 9 
[2,] 6 12 18 

In Octave:

mat_1 = [1,1,1;2,2,2]; 
mat_2 = [1,2,3;1,2,3;1,2,3]; 
mat_3 = mat_1*mat_2 

Der Ausgang ist:

mat_3 = 

    3 6 9 
    6 12 18 

In Python:

import numpy as np 

mat_1 = np.array([[1,1,1],[2,2,2]]) 
mat_2 = np.array([[1,2,3],[1,2,3],[1,2,3]]) 
mat_3 = np.dot(mat_1, mat_2) 
print(mat_3) 

Der Ausgang ist:

[[ 3 6 9] 
[ 6 12 18]] 

Für weitere Informationen über Matrix Skalarprodukte: https://en.wikipedia.org/wiki/Matrix_multiplication

EDIT 3

Die Ausgabe für sessionInfo() ist:

> sessionInfo() 
R version 3.4.0 (2017-04-21) 
Platform: x86_64-w64-mingw32/x64 (64-bit) 
Running under: Windows 7 x64 (build 7601) Service Pack 1 

Matrix products: default 

locale: 
[1] LC_COLLATE=Dutch_Netherlands.1252 LC_CTYPE=Dutch_Netherlands.1252 LC_MONETARY=Dutch_Netherlands.1252 
[4] LC_NUMERIC=C      LC_TIME=Dutch_Netherlands.1252  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

loaded via a namespace (and not attached): 
[1] compiler_3.4.0 tools_3.4.0 

EDIT 4

Ich versuchte, das bigalgebra Paket aber das schien nicht die Dinge zu beschleunigen:

library('bigalgebra') 

N <- 331 
M <- 23152 

mat_1 = matrix(rnorm(N*M,mean=0,sd=1), N, M) 
mat_1 <- as.big.matrix(mat_1) 
mat_2 = matrix(rnorm(N*M,mean=0,sd=1), M, M) 
tm3 <- system.time({ 
    mat_3 = mat_1%*%mat_2 
}) 
print(tm3) 

Die Ausgabe lautet:

user system elapsed 
101.79 0.00 101.81 

EDIT 5

James schlug meine zufällig generierten Matrix zu verändern:

N <- 331 
M <- 23152 

mat_1 = matrix(runif(N*M), N, M) 
mat_2 = matrix(runif(M*M), M, M) 
tm3 <- system.time({ 
    mat_3 = mat_1%*%mat_2 
}) 
print(tm3) 

Die Ausgabe lautet:

user system elapsed 
102.46 0.05 103.00 
+2

Die Geschwindigkeit von Rs Matrix-Operationen hängt von Ihrer R-Version ab und davon, ob die BLAS-Bibliotheken eingebunden sind. Eine einfache Möglichkeit ist die Installation von Microsoft R Open, oder Sie können es an [Intel MKL] (https : //software.intel.com/en-us/articles/using-intel-mkl-with-r). [Siehe hier für mehr] (https://simplystatistics.org/2016/01/21/parallel-blas-in-r/). –

+0

@ 李哲源 ZheyuanLi: Wenn du meinst, möchte ich das Skalarprodukt nehmen, dann ja? Soweit ich weiß, nehmen alle drei Implementierungen das Skalarprodukt aus zwei Matrizen, oder fehlt mir etwas? – BdB

+0

Mit 8 Kernen: R: 4 bis 5 Kerne, Python: 7 bis 8 Kerne, Oktave: 8 Kerne. In der Tat scheint es, dass R etwa die Hälfte der verfügbaren Verarbeitungsleistung verwendet. – BdB

Antwort

1

Basierend auf den Antworten von knb und Zheyuan Li habe ich begonnen, optimierte BLAS-Pakete zu untersuchen. Ich stieß auf GotoBlas, OpenBLAS und MKL, z.B. here.

Meine Schlussfolgerung ist, dass MKL BLAS bei weitem übertreffen sollte.

Es scheint, dass R aus der Quelle gebaut werden muss, um MKL zu integrieren. Stattdessen habe ich R Open gefunden. Dies hat MKL (optional) eingebaut, so dass die Installation ein Kinderspiel ist.

Mit dem folgenden Code:

N <- 331 
M <- 23152 

mat_1 = matrix(rnorm(N*M,mean=0,sd=1), N, M) 
mat_2 = matrix(rnorm(N*M,mean=0,sd=1), M, M) 
tm3 <- system.time({ 
    mat_3 = mat_1%*%mat_2 
}) 
print(tm3) 

Die Ausgabe lautet:

user system elapsed 
    10.61 0.10 3.12 

Als solche eine Lösung für dieses Problem zu verwenden MKL ist anstelle von Standard BLAS.

Allerdings sind meine realen Matrizen nach der Untersuchung sehr spärlich. Ich konnte diese Tatsache nutzen, indem ich das Matrix Paket verwendete. In der Praxis verwendete ich es wie z.B. Matrix(x = mat_1, sparse = TRUE), wobei mat_1 eine sehr dünne Matrix wäre. Dies reduzierte die Ausführungszeit auf ungefähr 3 Sekunden.

6

Dies ist eine triviale Operation ?? Die Matrixmultiplikation ist in linearen Algebra-Berechnungen immer eine teure Operation.

Eigentlich denke ich, dass es ziemlich schnell ist. Eine Matrixmultiplikation in dieser Größe hat

2 * 23.152 * 23.152 * 0.331 = 354.8 GFLOP 

100 Sekunden, um Ihre Leistung beträgt 3,5 GFLOPs. Beachten Sie, dass auf den meisten Computern die Leistung höchstens 0,8 GLOPs - 2 GFLOPs beträgt, es sei denn, Sie haben eine optimierte BLAS-Bibliothek.

Wenn Sie der Meinung sind, dass die Implementierung anderswo schneller ist, prüfen Sie die Möglichkeit der Verwendung von optimiertem BLAS oder paralleler Berechnung. R macht dies mit einem Standard-BLAS und ohne Parallelität.


Wichtige

Von R-3.4.0, sind weitere Werkzeuge mit BLAS zur Verfügung.

Zunächst einmal gibt sessionInfo() nun den vollständigen Pfad der verknüpften BLAS-Bibliothek. Ja, das zeigt nicht auf den symbolischen Link, sondern auf das endgültige gemeinsame Objekt! Die andere Antwort zeigt dies nur: Es hat OpenBLAS.

Das Timing-Ergebnis (in der anderen Antwort) impliziert, dass paralleles Computing (über Multi-Threading in OpenBLAS) vorhanden ist. Es ist schwer für mich, die Anzahl der verwendeten Threads zu bestimmen, aber es sieht so aus, als ob Hyperthreading aktiviert ist, da der Slot für "System" ziemlich groß ist!

Zweitens, options kann jetzt Matrix-Multiplikationen Methoden, über matprod. Obwohl dies eingeführt wurde, um mit NA/NaN umzugehen, bietet es auch Tests der Leistung!

  • "intern" ist eine Implementierung in nicht optimierten Triple Loop Nest. Dies ist in C geschrieben und hat die gleiche Leistung wie der Standard (Referenz) BLAS in F77 geschrieben;
  • "default", "blas" und "default.simd" bedeuten die Verwendung von verknüpften BLAS für die Berechnung, aber die Art der Überprüfung von NA und NaN unterscheidet sich. Wenn R mit Standard-BLAS verknüpft ist, dann hat es, wie gesagt, die gleiche Leistung mit "internal"; aber ansonsten sehen wir einen deutlichen Schub. Beachten Sie auch, dass R-Team sagt, dass "default.simd" in Zukunft möglicherweise entfernt wird.
1

Ich habe eine ähnliche Maschine: Linux-PC, 16 GB RAM, Intel 4770K,

Relevante Ausgabe von sessionInfo()

R version 3.4.0 (2017-04-21) 
Platform: x86_64-pc-linux-gnu (64-bit) 
Running under: Ubuntu 16.04.2 LTS 

Matrix products: default 
BLAS: /usr/lib/openblas-base/libblas.so.3 
LAPACK: /usr/lib/libopenblasp-r0.2.18.so 

locale: 
[1] LC_CTYPE=en_US.UTF-8  LC_NUMERIC=C    LC_TIME=de_DE.UTF-8  LC_COLLATE=en_US.UTF-8  
[5] LC_MONETARY=de_DE.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=de_DE.UTF-8  LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C    LC_MEASUREMENT=de_DE.UTF-8 LC_IDENTIFICATION=C  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] knitr_1.15.1 clipr_0.3.2 tibble_1.3.0 colorout_1.1-2 

loaded via a namespace (and not attached): 
[1] compiler_3.4.0 tools_3.4.0 Rcpp_0.12.10 

Auf meinem Rechner, Ihr Code-Snippet dauert ca. 5 Sekunden (gestartet RStudio, erstellt leere Datei .R, lief Schnipsel, output):

user system elapsed 
27.608 5.524 4.920 

snippet:

N <- 331 
M <- 23152 

mat_1 = matrix(rnorm(N*M,mean=0,sd=1), N, M) 
mat_2 = matrix(rnorm(N*M,mean=0,sd=1), M, M) 
tm3 <- system.time({ 
     mat_3 = mat_1 %*% mat_2 
}) 
print(tm3)