Vectorize min()用于矩阵

时间:2016-05-19 18:28:50

标签: r matrix vectorization

我希望对以下循环进行矢量化:

for (i in 1:n) {
    for (j in 1:m) {
        temp_mat[i,j]=min(temp_mat[i,j],1);
    }
}  

我以为我可以做temp_mat=min(temp_mat,1),但这并没有给我预期的结果。有没有办法对这个循环进行矢量化以使其更快?

2 个答案:

答案 0 :(得分:10)

只需使用temp_mat <- pmin(temp_mat, 1)即可。有关并行最小值的更多用法,请参阅?pmin

示例:

set.seed(0); A <- matrix(sample(1:3, 25, replace = T), 5)
#> A
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    3    1    1    3    3
#[2,]    1    3    1    2    3
#[3,]    2    3    1    3    1
#[4,]    2    2    3    3    2
#[5,]    3    2    2    2    1
B <- pmin(A, 2)
#> B
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    2    1    1    2    2
#[2,]    1    2    1    2    2
#[3,]    2    2    1    2    1
#[4,]    2    2    2    2    2
#[5,]    2    2    2    2    1

更新

由于您具有计算科学的背景,我想提供更多信息。

pmin很快,但远没有达到高绩效。它的前缀“parallel”仅表示element-wise。 R中“矢量化”的含义与HPC中的“SIMD矢量化”不同。 R是一种解释型语言,因此R中的“向量化”意味着选择C级循环而不是R级循环。因此,pmin只是用一个简单的C循环编码。

真正的高性能计算应该受益于SIMD矢量化。我相信你了解SSE / AVX内在函数。因此,如果您使用_mm_min_pd中的SSE2编写一个简单的C代码,您将从pmin获得~2倍的加速;如果您从AVX看到_mm256_min_pd,您将从pmin获得~4倍的加速。

不幸的是,R本身无法执行任何SIMD。我对Does R leverage SIMD when doing vectorized calculations?关于此问题的帖子有答案。对于您的问题,即使您将R链接到HPC BLAS,pmin也不会从SIMD中受益,因为pmin不涉及任何BLAS操作。所以更好的选择是自己编写编译代码。

答案 1 :(得分:4)

问题稍微有些混乱,因为min() 已经过矢量化。为了在这种特定情况下获得所需的结果,不必使用该功能。 逻辑子集提供了一种可能更有效(当然也更紧凑)的替代方案。

如果我正确理解了您想要的输出,可以使用一个命令实现代码中嵌套循环执行的矩阵修改:

temp_mat[temp_mat > 1] <- 1

希望这有帮助。

set.seed(123)
temp_mat <- matrix(2*runif(50),10)
#> temp_mat
#           [,1]       [,2]      [,3]       [,4]      [,5]
# [1,] 0.5751550 1.91366669 1.7790786 1.92604847 0.2856000
# [2,] 1.5766103 0.90666831 1.3856068 1.80459809 0.8290927
# [3,] 0.8179538 1.35514127 1.2810136 1.38141056 0.8274487
# [4,] 1.7660348 1.14526680 1.9885396 1.59093484 0.7376909
# [5,] 1.8809346 0.20584937 1.3114116 0.04922737 0.3048895
# [6,] 0.0911130 1.79964994 1.4170609 0.95559194 0.2776121
# [7,] 1.0562110 0.49217547 1.0881320 1.51691908 0.4660682
# [8,] 1.7848381 0.08411907 1.1882840 0.43281587 0.9319249
# [9,] 1.1028700 0.65584144 0.5783195 0.63636202 0.5319453
#[10,] 0.9132295 1.90900730 0.2942273 0.46325157 1.7156554
temp_mat[temp_mat > 1] <- 1
#> temp_mat
#           [,1]       [,2]      [,3]       [,4]      [,5]
# [1,] 0.5751550 1.00000000 1.0000000 1.00000000 0.2856000
# [2,] 1.0000000 0.90666831 1.0000000 1.00000000 0.8290927
# [3,] 0.8179538 1.00000000 1.0000000 1.00000000 0.8274487
# [4,] 1.0000000 1.00000000 1.0000000 1.00000000 0.7376909
# [5,] 1.0000000 0.20584937 1.0000000 0.04922737 0.3048895
# [6,] 0.0911130 1.00000000 1.0000000 0.95559194 0.2776121
# [7,] 1.0000000 0.49217547 1.0000000 1.00000000 0.4660682
# [8,] 1.0000000 0.08411907 1.0000000 0.43281587 0.9319249
# [9,] 1.0000000 0.65584144 0.5783195 0.63636202 0.5319453
#[10,] 0.9132295 1.00000000 0.2942273 0.46325157 1.0000000