[R Language] Angesichts der Beschleunigung der Berechnung des Trainingsmodells Aufzeichnung innerhalb von 1 Milliarde für Schleifen

1. Einleitung

Die Hauptmaschine des Autors ist MBA M1芯片(8+256). Eines Nachmittags, als ich den Zyklus konsolidierte, dachte ich plötzlich über ein Problem nach: Der kleine Zyklus kann schnell durchlaufen werden, und der mittlere Zyklus ist noch kaum da und läuft mit ein bisschen sehr langsam Stärke. Obwohl die CPU zu 100 % ausgelastet ist, scheinen die 8 Kerne nachzulassen, aber der 4核心8线程schwarze Apfel, der mir zugeworfen wurde, ist voll, was darauf hindeutet, dass mit ARM etwas nicht stimmt, wenn es Multithreading ist.

Die folgende Zahl liegt bei der Berechnung eines Trainingsmodells innerhalb von 1 Milliarde top:

2 mehrere Schleifen

2.1 Summen innerhalb von 100

### for
sum <- 0
for (i in 1:100) {
    
    
  sum <- sum + i
}
print(sum)

### while
sum <- 0
i <- 1
while (i <= 100) {
    
    
  sum <- sum + i
  i <- i + 1
}
print(sum)

2.2 Summe von ungeraden Zahlen/gerade Zahlen innerhalb von 100

### for
odd_sum <- 0
even_sum <- 0

for (i in 1:100) {
    
    
  if (i %% 2 == 0) {
    
    
    even_sum <- even_sum + i
  } else {
    
    
    odd_sum <- odd_sum + i
  }
}

print(paste("奇数和:", odd_sum))
print(paste("偶数和:", even_sum))

### while
odd_sum <- 0
even_sum <- 0
i <- 1

while (i <= 100) {
    
    
  if (i %% 2 == 0) {
    
    
    even_sum <- even_sum + i
  } else {
    
    
    odd_sum <- odd_sum + i
  }
  i <- i + 1
}

print(paste("奇数和:", odd_sum))
print(paste("偶数和:", even_sum))

3 Mehrfachschleifen

Das Folgende erfasst und liefert nur Ideen, spezifische Analysen der spezifischen Situation, aber eines ist 思维模式sehr vorteilhaft

3.1 Vektorisierung

Angenommen, Sie berechnen das Punktprodukt zweier Vektoren x und y, verwenden die for-Schleife, um separat zu reisen, zu multiplizieren und zu addieren:

x <- c(1, 2, 3, 4, 5)
y <- c(5, 4, 3, 2, 1)
dot_product <- 0
for (i in 1:length(x)) {
    
    
  dot_product <- dot_product + x[i] * y[i]
}
print(dot_product)

Die Vektorisierung kann als Check-in verstanden werden, das Highlight ist sum()die Summe *:

x <- c(1, 2, 3, 4, 5)
y <- c(5, 4, 3, 2, 1)
dot_product <- sum(x * y)
print(dot_product)

3.2 Zusammenführen von Schleifen

Nehmen Sie an, dass jedes Element in zwei Matrizen A und B durchlaufen, addiert und das Ergebnis in Matrix C gespeichert wird. Dies kann mit zwei verschachtelten for-Schleifen erreicht werden:

A <- matrix(1:9, 3, 3)
B <- matrix(10:18, 3, 3)
C <- matrix(0, 3, 3)
for (i in 1:nrow(A)) {
    
    
  for (j in 1:ncol(A)) {
    
    
    C[i, j] <- A[i, j] + B[i, j]
  }
}
print(C)

#输出结果:
     [,1] [,2] [,3]
[1,]   11   13   15
[2,]   17   19   21
[3,]   23   25   27

Aber um den Zweck dieses Typs zu verstehen, ist die Idee, Schleifen hier zusammenzuführen, nur die Addition von eins-zu-eins entsprechenden Zahlen in Matrizen:

A <- matrix(1:9, 3, 3)
B <- matrix(10:18, 3, 3)
C <- A + B
print(C)

3.3 Funktion anwenden

Angenommen, es gibt eine zweidimensionale 3x3-Matrixmatte, und jedes Element in der Matrix muss quadriert werden. Wir können dies mit einer for-Schleife tun:

mat <- matrix(1:9, 3, 3)
result <- matrix(0, 3, 3)
for (i in 1:nrow(mat)) {
    
    
  for (j in 1:ncol(mat)) {
    
    
    result[i, j] <- mat[i, j] ^ 2
  }
}
print(result)

Verwenden Sie apply+ function:

mat <- matrix(1:9, 3, 3)
result <- apply(mat, c(1, 2), function(x) x^2)
print(result)

3.4 Matrixoperationen

Angenommen, Sie müssen die inverse Matrix einer Matrix A berechnen, verwenden Sie eine for-Schleife und eine Matrixoperation, um Folgendes zu erreichen:

A <- matrix(c(1, 2, 3, 4), 2, 2)
det_A <- A[1, 1] * A[2, 2] - A[1, 2] * A[2, 1]
adj_A <- matrix(c(A[2, 2], -A[1, 2], -A[2, 1], A[1, 1]), 2, 2)
A_inv <- adj_A / det_A
print(A_inv)

#输出结果:
     [,1] [,2]
[1,] -2.0  1.0
[2,]  1.5 -0.5

Um diesen Schritt zu optimieren, ist es sehr einfach, direkt zu verwenden solve():

A <- matrix(c(1, 2, 3, 4), 2, 2)
A_inv <- solve(A)
print(A_inv)

3.5 für jede Zerlegungsaufgabe

foreachImplementieren Sie eine multithreaded for-Schleife mit Paket

library(foreach)
library(doParallel)

# 创建一个1000行,1000列的矩阵
m <- matrix(runif(1000000), nrow = 1000)

# 初始化并行计算环境
cl <- makeCluster(detectCores())
registerDoParallel(cl)

# 使用foreach包和%dopar%运算符进行并行计算
result <- foreach(i = 1:nrow(m), .combine = "+") %dopar% sum(m[i, ])

# 结束并行计算环境
stopCluster(cl)

# 输出结果
print(result)

Einige Leute werden sagen, ist das nicht nur eine Funktion?

Ja, aber nicht ganz, sonst warum manche Leute wissen, wie man diese Funktion benutzt, aber manche Leute müssen Schritt für Schritt rechnen (um nicht zu sagen, dass Schritt-für-Schritt-Rechnen nicht gut ist, nur wenn Sie es selbst berechnet und verstanden haben, kannst du wissen, wie man tief gräbt und es vereinfacht)

4. Diskussion

Wenn Sie nur eine Funktion kennen, kennen Sie sie, wissen aber nicht warum, aber Sie kennen nur den Berechnungsprozess und können ihn wie vor der Optimierung Schritt für Schritt berechnen. Dank der rasanten Entwicklung des Internets verfügt fast jeder über alle möglichen praktischen Tools und Open-Source-Methoden, 调包侠aber wenn die vorgefertigte Hilfe nicht ausreicht, muss immer noch zur untersten Schicht zurückgekehrt werden . In letzter Zeit war ich tief berührt: Ob Data Mining, Machine Learning, Deep Learning, Künstliche Intelligenz oder Full Stack, das Ende der Analyse ist der Algorithmus .

Guess you like

Origin blog.csdn.net/weixin_48093827/article/details/130508856