2012-10-08 5 views
1

메모리에 완전히로드 할 수없고 무작위로 액세스되는 매우 큰 메모리 맵핑 파일 (200GB 이상)을 처리하고 있습니다. 매핑 된 파일은 SSD (Solid State Drive Array)에 저장되지만 이전에 동일한 검색을 수행하고 사용 된 페이지가 이미 메모리에 읽혀지지 않으면 한 번에 하나씩 필요한 부분에 액세스하는 것이 매우 느립니다.C++ 메모리 맵핑 된 파일 데이터 프리 페치

mmap의 변수를 읽는 다중 스레드를 추가하면 속도가 크게 향상되고 테스트의 개선점에 도달 할 수 없었지만 1000 개가 넘는 스레드를 사용하면 openmp가 리소스를 사용할 수없는 오류를 발생시킵니다.

나는 (MADV_WILLNEED) 필요한 특정 부분을 커널에 알리기 위해 madvise를 시도했지만 커널이 차이를 만들기에 충분히 빨리 조언에 따라 행동하지 않는 것 같습니다.

나는 실제로 사용되기 직전에 필요한 데이터의 부분을 동시에 프리 페치 할 방법을 찾고있다. 어떤 변수 (또는 그것을 포함하는 매핑 된 파일의 메모리 페이지 크기의 조각)를 읽는 데 리소스를 많이 사용하지 않는 방법으로 읽지 않을 때 메모리에 강제로 저장하지 않아도됩니다.

블로킹을 피할 수없는 경우 훨씬 더 많은 수의 매우 가벼운 쓰레드를 실행하여 읽기 작업을 수행 할 수 있습니다.

+1

내가 원하는대로 혼란스러워합니다. madvise가 원하는대로하는 것처럼 들리지만 이전에 전화해야합니다. 디스크에서 데이터 블록을 요청하여 실제로 가져 오는 것 사이에는 약간의 지연이 있습니다. SSD라는 사실에 관계없이, 전체 I/O 시스템은 다소 지연 될 것입니다 (아마도 무시할 수 없을 것입니다). – CrazyCasta

+0

나는 그렇게 생각했을 것이다. 읽을 일괄 처리는 완전히 무작위이며 처리되는 항목은 150,000 개입니다. 각 항목은 약 2KB이며 식별 된 직후에 처리되므로 불행히도 이전에 madvise를 사용할 수 없습니다. 여러 스레드를 실행하여 전체 mmap 액세스 시간을 향상시키는 방법은 커널이 조언에 따라 작동하지 않는 것처럼 보이거나 많은 madvise 호출로 인해 잠재적으로 시간이 걸리는 것처럼 보입니다. – ridley3

+0

최상의 솔루션은 플랫폼 별 기능을 사용하는 것입니다. 플랫폼을 지정할 수 있습니까? –

답변

1

질문에 대한 답을 얻은 것 같습니다. 스레딩 외의 유일한 해결책은 수행 할 수있는 많은 액세스를 반복하는 것입니다. 각각 madvise입니다. 그런 다음 어떤 x 번호가 madvise (10,000이라고 말하면) 돌아와서 메모리에 액세스합니다. 그러나 O/S는 이 아니며은 madvise가 호출 된 순서대로 I/O가 수행됨을 보장합니다. 따라서 O/S는 첫 번째 madvise를 처리 한 다음 madvises의 끝으로 이동하거나 주소가 가장 낮은 주소로 점프 할 수 있습니다. 당신이 원하는 것처럼 들릴 정도로 I/O를 상당히 빠르게 할 수있는 방법은 없습니다.

예 :이 파일은 당신이 랜덤 액세스를 사용하는 경우 수행 할 작업을 정말 메모리 매핑 당신은 그러나 자신에게 물어해야

for(i=0; i < accesses + 10000; ++i) 
{ 
    madvise(access[i].addr, access[i].length, MADV_WILLNEED); 
    if(i >= 10000) 
    { 
     // Access location access[i-10000].addr 
    } 
} 

. 비동기 I/O가 더 나은 의미로 보일 것입니다.

+0

그런 종류의 madvise 루프가 정확하게 제가 시도한 것입니다. 그러나 큰 효과가없는 것 같습니다. – ridley3

+0

그러면 운영 체제가 madvise 호출 순서에 따라 I/O의 우선 순위를 결정하지 않을 가능성이 높습니다. 스레드 이외의 유일한 선택은 비동기 I/O를 사용하는 것입니다. – CrazyCasta

관련 문제