programing tip

R에서 루프가 느린 이유는 무엇입니까?

itbloger 2020. 10. 7. 07:25
반응형

R에서 루프가 느린 이유는 무엇입니까?


루프가 느리고 R대신 벡터화 된 방식으로 작업을 수행해야 한다는 것을 알고 있습니다.

하지만 왜? 루프가 느리고 apply빠른 이유는 무엇 입니까? apply몇 가지 하위 기능을 호출합니다. 빠르지 않은 것 같습니다.

업데이트 : 죄송합니다. 질문이 잘못되었습니다. 벡터화와 apply. 내 질문은,

"벡터화가 더 빠른 이유는 무엇입니까?"


R의 루프는 모든 해석 언어가 느린 것과 같은 이유로 느립니다. 모든 작업에는 많은 추가 수하물이 있습니다.

R_execClosurein을eval.c 보세요 (이것은 사용자 정의 함수를 호출하기 위해 호출되는 함수입니다). 거의 100 줄에 달하며 실행을위한 환경 생성, 환경에 인수 할당 등 모든 종류의 작업을 수행합니다.

C에서 함수를 호출 할 때 발생하는 일이 얼마나 적은지 생각해보십시오 (인수를 스택, 점프, 팝 인수로 푸시).

그래서 당신은 다음과 같은 타이밍을 얻습니다 (조란이 주석에서 지적했듯이 실제로 apply는 빠르지 않습니다 . 빠르고 내부 C 루프입니다 mean. apply단지 일반적인 오래된 R 코드입니다) :

A = matrix(as.numeric(1:100000))

루프 사용 : 0.342 초 :

system.time({
    Sum = 0
    for (i in seq_along(A)) {
        Sum = Sum + A[[i]]
    }
    Sum
})

합계 사용 : 측정 할 수 없을 정도로 작음 :

sum(A)

점근 적으로 루프가 다음과 같이 훌륭하기 때문에 약간 당황 스럽습니다 sum. 느려 야하는 실질적인 이유가 없습니다. 반복 할 때마다 더 많은 추가 작업을 수행하는 것입니다.

따라서 다음을 고려하십시오.

# 0.370 seconds
system.time({
    I = 0
    while (I < 100000) {
        10
        I = I + 1
    }
})

# 0.743 seconds -- double the time just adding parentheses
system.time({
    I = 0
    while (I < 100000) {
        ((((((((((10))))))))))
        I = I + 1
    }
})

(이 예는 Radford Neal에 의해 발견되었습니다 )

때문에 (R은 운영자이며, 실제로 당신이 그것을 사용할 때마다 조회의 이름을 필요로 :

> `(` = function(x) 2
> (3)
[1] 2

또는 일반적으로 해석 된 작업 (모든 언어)에는 더 많은 단계가 있습니다. 물론 이러한 단계는 이점도 제공합니다 . C 에서는 이러한 (트릭을 수행 할 수 없습니다 .


루프가 항상 느리고 apply빠르지는 않습니다. R News 2008 년 5 월호에 이에 대한 좋은 토론이 있습니다 .

Uwe Ligges와 John Fox. R 헬프 데스크 : 어떻게이 루프를 피하거나 더 빠르게 만들 수 있습니까? R News, 8 (1) : 46-50, 2008 년 5 월.

"루프!"섹션에서 (48 페이지부터 시작), 그들은 말합니다 :

R에 대한 많은 의견은 루프를 사용하는 것이 특히 나쁜 생각이라고 말합니다. 이것은 반드시 사실이 아닙니다. 경우에 따라 벡터화 된 코드를 작성하기 어렵거나 벡터화 된 코드가 엄청난 양의 메모리를 소비 할 수 있습니다.

그들은 또한 다음을 제안합니다.

  • 새 객체를 루프 내에서 크기를 늘리는 대신 루프 전에 전체 길이로 초기화합니다.
  • 루프 외부에서 수행 할 수있는 작업을 루프에서 수행하지 마십시오.
  • 단순히 루프를 피하기 위해 루프를 피하지 마십시오.

for루프에 1.3 초가 걸리지 만 apply메모리가 부족한 간단한 예가 있습니다.


The only Answer to the Question posed is; loops are not slow if what you need to do is iterate over a set of data performing some function and that function or the operation is not vectorized. A for() loop will be as quick, in general, as apply(), but possibly a little bit slower than an lapply() call. The last point is well covered on SO, for example in this Answer, and applies if the code involved in setting up and operating the loop is a significant part of the overall computational burden of the loop.

Why many people think for() loops are slow is because they, the user, are writing bad code. In general (though there are several exceptions), if you need to expand/grow an object, that too will involve copying so you have both the overhead of copying and growing the object. This is not just restricted to loops, but if you copy/grow at each iteration of a loop, of course, the loop is going to be slow because you are incurring many copy/grow operations.

The general idiom for using for() loops in R is that you allocate the storage you require before the loop starts, and then fill in the object thus allocated. If you follow that idiom, loops will not be slow. This is what apply() manages for you, but it is just hidden from view.

Of course, if a vectorised function exists for the operation you are implementing with the for() loop, don't do that. Likewise, don't use apply() etc if a vectorised function exists (e.g. apply(foo, 2, mean) is better performed via colMeans(foo)).


Just as a comparison (don't read too much into it!): I ran a (very) simple for loop in R and in JavaScript in Chrome and IE 8. Note that Chrome does compilation to native code, and R with the compiler package compiles to bytecode.

# In R 2.13.1, this took 500 ms
f <- function() { sum<-0.5; for(i in 1:1000000) sum<-sum+i; sum }
system.time( f() )

# And the compiled version took 130 ms
library(compiler)
g <- cmpfun(f)
system.time( g() )

@Gavin Simpson: Btw, it took 1162 ms in S-Plus...

And the "same" code as JavaScript:

// In IE8, this took 282 ms
// In Chrome 14.0, this took 4 ms
function f() {
    var sum = 0.5;
    for(i=1; i<=1000000; ++i) sum = sum + i;
    return sum;
}

var start = new Date().getTime();
f();
time = new Date().getTime() - start;

참고URL : https://stackoverflow.com/questions/7142767/why-are-loops-slow-in-r

반응형