2009-06-18 4 views
5

매우 CPU 집약적 인 (프로 시저 바인딩 된) 과학적 소프트웨어로 작업하고 있지만 디스크에 데이터를 자주 작성해야합니다./o 경계).계산 집약적 인 작업을 수행하는 동안 디스크에 데이터를 효율적으로 저장하는 방법

이 (OpenMP)에 병렬 처리를 추가하고 디스크 쓰기 요구 사항을 해결하는 가장 좋은 방법이 무엇인지 궁금합니다. 시뮬레이션이 HDD에서 기다려야하는 이유는 없습니다 (현재 진행중입니다).

나는 이것을위한 '우수 사례'를 찾고 있는데, 속도는 내가 가장 신경 쓰는 부분이다 (이것들은 대단히 긴 시뮬레이션 일 수있다). 하나의 CPU 바인딩 (시뮬레이션)이고 다른 하나는 IO-바인딩 :

감사 ~ 알렉스

먼저 생각 : 시뮬레이션은 두 개의 프로세스를 가지고 있으므로 별도의 프로세스를 가진

디스크에 실제 기록을 (파일 쓰기). 이것은 복잡하게 들린다.

아마도 파이프/버퍼일까요? 나는 이것들에 익숙하지 않으므로 가능한 해결책 일 수 있습니다.

답변

2

당신이 당신의 프로그램의 OpenMP를 구현하는 경우,이 파일에 저장 병렬 섹션에서 의 #pragma OMP 단일 또는 의 #pragma OMP 마스터를 사용하는 것이 좋습니다. 이 pragma를 사용하면 하나의 스레드 만 무언가를 실행할 수 있습니다. 따라서 코드는 다음과 같이 보일 수 있습니다 :

#pragma omp parallel 
{ 
    // Calculating the first part 
    Calculate(); 

    // Using barrier to wait all threads 
    #pragma omp barrier 

    #pragma omp master 
    SaveFirstPartOfResults(); 

    // Calculate the second part 
    Calculate2(); 

    #pragma omp barrier 

    #pragma omp master 
    SaveSecondPart(); 

    Calculate3(); 

    // ... and so on 
} 

여기서 스레드 그룹은 계산을 수행하지만 단일 스레드 만 결과를 디스크에 저장합니다.

소프트웨어 파이프 라인처럼 보입니다. 필자는 인텔 스레딩 빌딩 블록 라이브러리에서 tbb :: pipeline 패턴을 고려하도록 제안합니다. http://cache-www.intel.com/cd/00/00/30/11/301132_301132.pdf#page=25에서 소프트웨어 파이프 라인에 대한 자습서를 참조 할 수 있습니다. 4.2 절을 읽으십시오. 그들은 문제를 해결했습니다 : 드라이브에서 읽는 하나의 스레드, 읽기 문자열을 처리하는 두 번째 스레드, 드라이브에 저장하기위한 세 번째 스레드.

5

데이터를 저장하기 위해 다른 스레드를 생성하는 것이 가장 좋은 방법이라고 할 수 있습니다. 완전히 새로운 프로세스는 아닙니다. 새로운 프로세스에서는 프로세스 경계를 ​​넘어서 저장 될 데이터를 전달해야하는 번거 로움을 겪습니다. 이로 인해 새로운 어려움이 발생합니다.

0

하나의 스레드가 연산 집약적 프로세스의 단계를 지속적으로 실행 한 다음 부분 결과의 큐에 부분 결과를 추가합니다. 다른 스레드는 큐에서 부분 결과를 지속적으로 제거하여 디스크에 씁니다. 대기열에 대한 액세스를 동기화하십시오. 대기열은 항목을 끝에 추가하고 앞에서 항목을 제거 할 수있는 목록 형식의 데이터 구조입니다.

1

CPU 및 IO 바운드이므로 다음과 같이 추측하겠습니다. 아직 많은 메모리가 남아 있습니다. 맞습니까?

그렇다면 메모리에 디스크에 기록해야하는 데이터를 일정 기간 버퍼링해야합니다. 거대한 데이터 덩어리를 쓰는 것은 일반적으로 작은 조각을 쓰는 것보다 훨씬 빠릅니다.

쓰기 자체 : 메모리 매핑 IO 사용을 고려하십시오. 내가 벤치마킹 한 이후로 시간이 지났지 만 지난번에 내가 한 일은 훨씬 더 빠 릅니다.

또한 CPU와 IO를 항상 조금씩 교환 할 수 있습니다. 현재 데이터를 압축되지 않은 원시 데이터로 쓰고 있다고 생각합니다. 맞습니까? 간단한 압축 체계를 사용하여 기록 할 데이터의 양을 줄이면 일부 IO 성능을 얻을 수 있습니다. ZLIB 라이브러리는 작업하기가 쉽고 압축률이 가장 낮은 레벨에서 매우 빠르게 압축됩니다. 데이터의 특성에 따라 다르지만, 많은 중복성이있는 경우 매우 조잡한 압축 알고리즘조차도 IO 바인딩 문제를 제거 할 수 있습니다.

3

마음에 떠오르는 첫 번째 해결책은 시뮬레이션에서 작성자까지 단방향 파이프를 사용하여 자체 프로세스에서 디스크 쓰기를하는 것입니다. 작성자는 최대한 빨리 글을 씁니다 (파이프에서 새 데이터 그리기). 이것에 대한 문제는 만약 sim이 작가보다 너무 멀리 앞서 간다면 sim은 파이프 쓰기를 막을 것이고 그것은 하나의 제거에서 I/O bound가 될 것입니다.

실제로 시뮬레이션 사이클은 결과가 침투 될 때까지 완료되지 않습니다.

나에게 발생하는 두 번째 문제는 논 블로킹 I/O를 사용하는 것입니다.시뮬레이션을 쓸 때마다 비 차단 I/O를 통해이를 수행해야합니다. 다음에 쓸 필요가있을 때 새로운 I/O 작업을 시작하기 전에 이전 I/O 작업 결과를 가져올 수 있습니다. 이렇게하면 시뮬레이션이 I/O와 가능한 한 많이 실행되도록하여 시뮬레이션이 작성보다 훨씬 앞당길 수 있습니다.

평균적으로 쓰기가 시뮬레이션을 따라갈 수 있기 때문에 시뮬레이션 처리주기가 다양 할 때 (때로는 쓰기 시간보다 작을 때도 있음) 첫 번째 해결 방법이 더 좋습니다.

처리주기가 항상 (또는 거의 항상) 쓰기 시간 인 보다 짧을 경우 파이프를 사용하는 경우 비 차단 입출력을 사용하는 것이 좋습니다. 그것은 결국 채울 것이고 시뮬레이션은 I/O에서 멈추게 될 것입니다.

+0

나는 1 방향 파이프가 내가 갈 방법이라고 생각한다. 나는 너무 심하게 막는 문제에 직면 할 것이라고 생각하지 않는다. theres 많은 데이터가 생성되지, 난 단지 스레드를 분리 싶었어요. 많은 양의 데이터를 생성하는 경우 실제 보관해야 할 데이터 양을 재고해야합니다. – machinaut

0

응용 프로그램에 두 개의 스레드 (CPU는 하나, 하드 디스크는 하나)이 있어야합니다.

는 CPU 스레드 푸시 하드 디스크 스레드가 다음 데이터에 온다 가져옵니다 큐에 데이터를 완료했습니다.

이 방법은 CPU가 데이터 만 제거하고 다른 사람이 그 하드를 처리 할 수 ​​있습니다됩니다 드라이브는 대기열에있는 모든 데이터를 기다립니다.

구현을하면 객체의 공유 메모리 유형으로 큐를 처리 할 수 ​​있지만 파이프가 사용자가 찾고자하는 것과 정확히 일치한다고 생각합니다. CPU는 필요할 때 파이프에 쓰기 만합니다. 하드 디스크 쪽에서는 파이프를 읽고 유효한 데이터를 얻을 때마다 거기에서부터 진행합니다.