2013-05-29 2 views
6

나는 검증을위한 일련의 규칙이 주어지면, C 슬라이스를 '조각'으로 분해하고 각 슬라이스를 검증하는 C 시뮬레이션을 코딩하고있다. (기본 아이디어는 순서가 중요하며 규칙의 실제 의미는 그 위에있는 몇 가지 규칙의 영향을 받기 때문에 각 규칙과 그 위에 겹쳐있는 규칙 만 사용하여 '조각'을 만들 수 있습니다. 일반적으로 전체 시퀀스보다 훨씬 작은 조각입니다.)스택을 능가하는 힙 솔루션?

내 문제는 다음과 같습니다.

구조체 (규칙)의 배열과 int (길이)를 포함하는 struct (policy)가 있습니다. 내 원래 구현은 후한의 malloc과 realloc을 사용 :

struct{ 
    struct rule *rules; 
    int length; 
}policy; 
... 
struct policy makePolicy(int length) 
{ 
    struct policy newPolicy; 
    newPolicy.rules = malloc(length * sizeof(struct rule)); 
    newPolicy.length = length; 
    return newPolicy; 
} 
... 
struct policy makeSlice(struct policy inPol, int rulePos) 
{ 
    if(rulePos > inPol.length - 1){ 
    printf("Slice base outside policy \n"); 
    exit(1); 
    } 
    struct slice = makePolicy(inPol.length); 
    //create slice, loop counter gets stored in sliceLength 
    slice.rules = realloc(slice.rules, sliceLength * sizeof(struct rule)); 
    slice.length = sliceLength; 
    return slice; 
} 

이 malloc으로 할당 한 메모리를 사용하면서, 나는 그것이 힙 많이 사용한다 있으리라 믿고있어. 이제 malloc이없는 실험용 병렬 시스템으로 이식하려고합니다.

슬픈 듯이 모든 것을 고정 크기 배열로 할당했습니다.

이제 충격을받습니다.

새 코드가 더 느리게 실행됩니다. 훨씬 느립니다.

(슬라이스 길이가 200이고, 한 시간이 300을 넘을 때까지 기다리는 데 사용 된 원래 코드 ... 이제 슬라이스 길이가 70, 80 ... 인 경우 시간이 오래 걸렸습니다. 아직은 200이 아닙니다.)

유일한 점은 전체 정책 (MAXBUFLEN은 10000)과 동일한 메모리가 슬라이스에 주어 지지만 전체가 실행되지 않는 것입니다. 전혀 메모리가 없습니다. 'top'은 소비 된 총 메모리가 이전과 마찬가지로 수십 메가 바이트 범위라는 것을 의미합니다. (그리고 물론 길이를 저장하는 동안, 나는 모든 것을 반복하지 않고 실제 규칙을 가진 부분 만 반복합니다.)

왜 갑자기 왜 그렇게 느린지 설명해 주시겠습니까?

+0

프로필러를 사용해 보셨습니까? 새 컴퓨터 또는 동일한 컴퓨터에서 느리게 실행됩니까? –

+0

이제 같은 컴퓨터에서 더 느리게 실행된다는 의미입니까? 아니면 "실험 병렬"머신에서 더 느리게 실행됩니까? – jalf

+0

지금까지는 동일한 컴퓨터에 있습니다. 나는 평행선에서 아직 그것을 달리지 않았다. 내가 추가해야합니다. 검증은 pow (n, 5) 명령입니다. 여기서 n은 규칙의 수입니다. 그래서 나는 검증에 시간이 걸린다고 생각한다. 지금 gprof를 배우려고합니다. 프로필을 작성하고 이에 대한 답변을 더 잘 할 수 있습니다. – user2431187

답변

3

구조체의 크기를 더 큰 크기 (예 : 10000 개의 규칙)로 고정하면 캐시 위치가 원래 크기보다 훨씬 더 커질 수 있습니다. 프로파일 러 (Valgrind의 oprofile 또는 cachegrind)를 사용하여 캐시가 문제인지 확인할 수 있습니다.

원본 프로그램에서 한 캐시 라인은 최대 8 개의 struct policy (64 비트 캐시 라인이있는 32 비트 시스템)을 유지할 수 있습니다. 그러나 수정 된 버전에서는 현재 캐시 라인 크기보다 훨씬 크기 때문에 하나만 보유 할 수 있습니다.

length 필드를 위로 이동하면 length과 처음 몇 개의 struct rule 개가 단일 캐시 라인에 들어갈 수 있으므로이 경우 성능을 향상시킬 수 있습니다.

struct policy{ 
    int length; 
    struct rule rules[10000]; 
}; 

이 문제를 해결하려면 캐시 위치를 보장하기 위해 사용자 지정 할당자를 작성해야합니다. 이 프로그램의 병렬 버전을 작성하는 경우 캐시 라인 경합을 피하기 위해 다른 스레드가 사용하는 메모리를 다른 캐시 라인으로 분리해야합니다.

+0

현장 실습 아이디어에 감사드립니다. 그러나 지금까지 별다른 차이를 내지 않았 음이 두렵습니다. 주문 스위치를 구현했지만 이전 버전에서 깜박 인 50-75 규칙을 사용하는 슬라이스는 여전히 몇 분 동안 화면 상에 남아 있습니다. Valgrind를 살펴 보겠다.하지만 내 자신의 할당자를 작성할 수있는 방법에 대한 조언과 스레드마다 메모리를 분리 할 수있는 방법에 대해 많은 조언을드립니다. – user2431187

+0

@ user2431187 캐시 문제가 발생할 수있는 것 이상의 성능 차이가있는 것으로 보입니다. 데이터 구조 이외의 다른 프로그램을 변경 했습니까? – Naruil

+0

코드에 대한 유일한 다른 변경 사항은 고정 길이 배열을 사용하여 probe() 함수에서 테스트 데이터 요소를 보유한다는 것입니다. (이것은 꽤 큰 배열이지만 여전히 메가 바이트 정도는 아닙니다.) 테스트로서 데이터 포인트 배열에 malloc()을 사용하여 코드를 다시 편집했습니다. 내 테스트에서이 코드는 정적 배열 만 가진 코드보다 빠르지 만 malloc()이 사용하는 코드만큼 빠르지는 않습니다. (가장 큰 슬라이스의 길이가 130이고 동적 코드의 경우 30 분 이상, 전체 코드의 경우 밤이 걸리는 예제를 말하십시오.) – user2431187

관련 문제