2010-01-02 8 views
3

저는 iPhone 앱으로 디버깅/최적화 단계에 있습니다. 하나의 병목이 남아 있습니다 - 프로그램에서 눈에 띄는 지연이있는 유일한 곳은 다음과 같습니다 : (그런데, 문자와 문자로 바스의 이름을 바꿨습니다. (실제 이름은 훨씬 더 인간이 읽을 수 있습니다. 실제 응용 프로그램에서,하지만 문맥 약간의 ​​의미를, 그래서이 충분히 명확 바랍니다) 여기에 루프입니다 :..이 루프를 최적화 할 수 있습니까?

for(i=0;i<xLong; i+=yFloat*zShort){ 
    aFloat=0.0; 
    for(int j=i;j<i+yFloat*zShort;j++){ 
    aFloat=hArray[j]/kFloat; 
    } 
    bNSNumber = [NSNumber numberWithFloat:aFloat]; 
    [cNSMutableArray addObject:bNSNumber]; 
} 

모든 이의 생성 및 청소는이 루프의 외부에있다가

을 (여기서 일어나는 일들은 꽤나 간단합니다. 그러나 기본적으로 저는 수백만 개의 매우 큰 배열을 가지고 있습니다. 그리고 그 배열을 통해 yFloat * zShort 길이의 청크로 가서 그 청크의 모든 요소를 ​​추가하고, 최종 배열을 다른 배열에 삽입합니다. hArray가 백만 엘리먼트 길이이고 청크 길이가 200 인 경우 처음 200 개의 요소를 합산하고 그 합계를 cNSMutableArray에 삽입 한 다음 hArray의 다음 200 개 요소로 이동합니다. 결국, cNSMutableArray 길이는 5000 요소가됩니다.)

외부 루프가 약 25k이고 내부 루프가 약 200이면이 코드는 실행하는 데 약 4 초가 걸립니다. 현실 세계에서와 같이 가능한 한 많은 것을 내리고 싶습니다. 바깥 쪽 루프가 약간 더 클 수도 있습니다.

아이디어를 빠르게 만드는 방법은 무엇입니까?

아이디어를 제공해 주셔서 감사합니다.

답변

6

우선 해제, 당신의 묘사에서 그것은 내부 루프 같은 소리해야 ,

for(int j=i;j<i+yFloat*zShort;j++){ 
    aFloat+=hArray[j]/kFloat; 
} 

어쨌든 kFloat가 변경되지 않기 때문에, 당신은 루프에서 그것을 이동할 수 있습니다 한 번 분할을 수행합니다 : 읽기

for(int j=i;j<i+yFloat*zShort;j++){ 
    aFloat+=hArray[j]; 
} 
aFloat/=kFloat; 

이것은 최종 가치의 정확성에 영향을 미칠 수 있다고 말했습니다. 네가하는 일을 정확히 알지 못한다면 그게 중요한지 나는 모른다.

+1

아하! 당신이 버그를 발견했습니다! 나는 실제로 블록을 요약하지는 않았다. 명백하게 그것이 원래의 의도 였지만 어떤 시점에서 보였습니다. 나는 그 일을 그만 두었습니다. 즉, 각 단계를 초기화하는 것입니다. 물론 그럴 필요는 없습니다. 그래서 내부 루프를 완전히 제거했습니다. 그 값을 해당 청크의 첫 번째 값으로 설정하면 시간은 이전의 1/4이됩니다. 감사! –

+0

@ Eric Christensen : 기능 제거를 통한 최적화는 흥미로운 접근 방법입니다. 첫 번째 요소의 사용이 블록의 평균만큼 좋은 이유는 궁금합니다. –

+0

게시 한 코드는 실제로 청크의 마지막 값을 사용합니다. 중요한 경우 첫 번째 값이 아닙니다. –

8

NSMutableArray를 사용하는 대신 C 스타일 부동 배열을 만들려고 했습니까? 많은 래퍼 (NSNumber)를 생성하는 오버 헤드가 합산 될 수 있습니다.

+0

감사합니다. 원래 데이터 길이는 알려지지 않았지만 지금은 그렇습니다. 그렇기 때문에 C 스타일 배열로 다시 변환하는 것이 좋습니다. 그럴거야. –

0

이것은 배경 스레드에서 분리되어야하는 계산의 종류처럼 보입니다.

당신은 몇 가지 옵션 - NSOperation은 실행 가능한 대안이 있지만 데이터 구조에 따라이 detachNewThreadSelector를 사용하는 것이 더 쉬울 수 있습니다 toTarget : withObject를 :

+0

불행히도 루프가 끝날 때까지는 사용자가 할 수있는 것이 아무것도 없으므로이 기능을 사용하지 않아도됩니다.백그라운드 스레드에는 속도 이점이 없습니다. 동시에 다른 일을 동시에 할 수 있다는 것입니다. 감사. –

+0

하지만 objective-c가 windows forms와 비슷하다면 GUI가 잠길 것입니다. 그렇게하면 진행률 막대 또는 무언가를 만들 수 있습니다. – RCIX

+0

예, 그게 내가 얻는 것입니다. GUI를 잠그는 것은 매우 나쁜 형태입니다 .- 가능한 경우 취소 가능한 진행률 표시 줄 또는 작업 진행 중 표시를 표시하는 것이 훨씬 낫습니다. – sbooth

0

좁은 루프 안에 개체를 만들지 않으려는 경우가 있습니다. 그렇게 할 때마다 해시 삽입과 관련된 힙에 새 객체를 할당합니다.

+0

아마도 뭔가를 놓친 것 같습니다. 내가 아는 한, 위의 코드는 루프 내에 새로운 객체를 생성하지 않습니다. –

2

나는 이미 당신이 멋진 스피드 업을 가지고 있다고보고 있지만, 여기에 나의 두 센트가있다 : 부동 소수점 부는 유명하다.

float invKFloat = 1.0f/kFloat; 

그리고 나서 이것을 kFloat으로 나누는 대신에 mulitply 할 수 있습니다. 즉, 외부 루프에서 매번 대신가 아니라 한 번만 나누기 만하면됩니다.

관련 문제