toc
1 前言
笔者主力机是MBAM1芯片(8 256)
,某个下午巩固循环突然思考到个问题,小循环很快就能run出来,中循环还勉勉强强,稍微上点强度就运行的很慢。虽然是CPU占用100%,8颗核心好像是偷着懒跑的,但是丢给我那台4核心8线程
黑苹果,是跑满的,说明ARM在多线程的时候,有点东西
下图是计算一个10亿内训练模型时的top
:
2 几个循环
2.1 100以内的和
代码语言:text复制### 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 100以内奇数和/偶数和
代码语言:text复制### 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 多重循环
以下仅记录和提供思路,具体情况具体分析,但是有一点思维模式
很得益
3.1 向量化
假设计算两个向量x和y的点积,使用for循环分别游历,相乘再相加:
代码语言:text复制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)
向量化,可以理解为对号入座,亮点就是sum()
和*
:
x <- c(1, 2, 3, 4, 5)
y <- c(5, 4, 3, 2, 1)
dot_product <- sum(x * y)
print(dot_product)
3.2 合并循环
假设对两个矩阵A和B中的每个元素进行遍历,将它们相加,并将结果保存到矩阵C中。可以使用两个嵌套的for循环实现:
代码语言:text复制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
但是理解这类的目的,合并循环的思路在这里刚好就是矩阵一一对应的数字相加:
代码语言:text复制A <- matrix(1:9, 3, 3)
B <- matrix(10:18, 3, 3)
C <- A B
print(C)
3.3 apply函数
假设有一个3x3的二维矩阵mat,需要将矩阵中每个元素求平方。我们可以使用for循环来实现:
代码语言:text复制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)
用apply
function
:
mat <- matrix(1:9, 3, 3)
result <- apply(mat, c(1, 2), function(x) x^2)
print(result)
3.4 矩阵运算
假设需要计算一个矩阵A的逆矩阵,使用for循环和矩阵运算实现:
代码语言:text复制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
若要优化这一步骤,很简单,直接用solve()
:
A <- matrix(c(1, 2, 3, 4), 2, 2)
A_inv <- solve(A)
print(A_inv)
3.5 foreach分解任务
用foreach
包实现多线程for循环
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)
有人会说,这不就是用了个函数吗?
是,但又不完全是,不然为何有人懂得用这个函数,但有人需要一步一步算(并非说一步一步算不好,只有自己算过,理解了,才懂得去挖掘深度,化繁为简)
4 讨论
如果只知道个函数是知其然而不知其所以然,但是只知道计算过程便如优化前的一样,一步一步计算。得益于现在互联网发展的飞起,各种便利工具各种开源方法,几乎人人都是调包侠
,但是当现成的辅佐无法满足时还是需要回归底层。最近深有感触,不论是数据挖掘、还是机器学习深度学习、人工智能、全栈,分析的尽头就是算法。