계산 집약적인 작업을 실행하는 동안 디스크에 데이터를 저장하는 효율적인 방법

StackOverflow https://stackoverflow.com/questions/1014113

문제

저는 CPU 집약적(프로시저 바운드)을 많이 사용하는 과학적인 소프트웨어를 작업하고 있지만 꽤 자주(I/O 바운드) 디스크에 데이터를 써야 합니다.

나는 이것(OpenMP)에 병렬화를 추가하고 있으며 디스크에 쓰기 요구 사항을 해결하는 가장 좋은 방법이 무엇인지 궁금합니다.시뮬레이션이 HDD(현재 수행 중인 작업)에서 기다려야 할 이유가 없습니다.

나는 이에 대한 '모범 사례'를 찾고 있으며, 속도는 내가 가장 중요하게 생각하는 것입니다(이것은 매우 긴 시뮬레이션일 수 있습니다).

감사합니다 ~ 알렉스

첫 번째 생각:

별도의 프로세스가 있으면 실제로 디스크에 쓰기가 수행되므로 시뮬레이션에는 두 가지 프로세스가 있습니다.하나는 CPU 바인딩(시뮬레이션)이고 다른 하나는 IO 바인딩(파일 쓰기)입니다.복잡해 보이네요.

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

도움이 되었습니까?

해결책

프로그램에 OpenMP를 구현하는 경우 사용하는 것이 좋습니다. #pragma omp 싱글 또는 #Pragma OMP 마스터 병렬 섹션에서 파일에 저장까지. 이 pragmas는 하나의 스레드만이 무언가를 실행할 수있게합니다. 따라서 코드는 다음과 같이 볼 수 있습니다.

#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 :: 파이프 라인 패턴을 고려해야합니다. 소프트웨어 파이프 라인에 대한 자습서를 참조 할 수 있습니다. http://cache www.intel.com/cd/00/00/30/11/301132_301132.pdf#page=25. 단락 4.2를 읽으십시오. 그들은 문제를 해결했습니다. 하나는 드라이브에서 읽을 하나, 두 번째 스레드, 두 번째 스레드, 문자열을 처리하고 세 번째는 드라이브에 저장합니다.

다른 팁

가장 좋은 방법은 데이터를 저장하기 위해 완전히 새로운 프로세스가 아닌 다른 스레드를 생성하는 것입니다.새로운 프로세스를 사용하면 프로세스 경계를 ​​넘어 저장할 데이터를 전달해야 하는 문제가 발생하며 이로 인해 새로운 어려움이 발생합니다.

가장 먼저 떠오르는 솔루션은 당신이 말한 것입니다. 디스크는 심에서 작가로 일방 통행 파이프를 사용하여 자체 프로세스에 글을 쓰는 것입니다. 작가는 가능한 한 빨리 씁니다 (파이프에서 새로운 데이터를 그리는). 이것의 문제점은 심이 작가보다 훨씬 앞서 나가면 SIM이 파이프를 어쨌든 차단할 것이며, 한 번의 제거에 I/O 묶을 것입니다.

문제는 실제로 시뮬레이션주기가 결과를 뱉을 때까지 완료되지 않는다는 것입니다.

나에게 발생하는 두 번째는 비 블로킹 I/O를 사용하는 것입니다. SIM이 작성해야 할 때마다 비 차단 I/O를 통해 그렇게해야합니다. 다음으로 쓸 필요가 있으면 새 제품을 시작하기 전에 이전 I/O 운영 결과 (작은 대기가 발생할 수 있음)의 결과를 선택할 수 있습니다. 이렇게하면 시뮬레이션이 필기보다 훨씬 앞서 나오지 않으면 서 시뮬레이션을 I/O와 병렬로 실행할 수 있습니다.

시뮬레이션 처리주기가 변하는 경우 첫 번째 솔루션이 더 나을 것입니다 (때로는 쓰기 시간보다 때로는 작음이 많고 때로는 더 길어짐) 평균적으로 쓰기가 SIM을 따라갈 수 있기 때문입니다.

처리주기가 항상 (또는 거의 항상) 쓰기 시간보다 짧은 경우 파이프를 귀찮게하지 않고 파이프를 사용하면 결국에는 채우기 때문에 블로킹 I/O 만 사용할 수 있습니다. 그리고 SIM은 어쨌든 I/O에 매달릴 것입니다.

당신은 CPU와 IO 바운드이기 때문에 : 추측하겠습니다 : 여전히 많은 메모리가 있습니다.

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

쓰기 자체의 경우 : 메모리 매핑 된 IO를 사용하는 것을 고려하십시오. 벤치마킹 이후 오랜 시간이 지났지 만 지난번에 내가 한 일은 더 빨랐습니다.

또한 항상 CPU 대 IO의 거래를 할 수 있습니다. 나는 당신이 현재 데이터를 일종의 원시적이고 압축되지 않은 데이터로 쓰고 있다고 생각합니다. 간단한 압축 체계를 사용하여 작성할 데이터의 양을 줄이면 일부 IO 성능을 얻을 수 있습니다. Zlib 라이브러리는 작업하기가 매우 쉽고 압축 수준에서 가장 빠르게 압축됩니다. 그것은 데이터의 특성에 따라 다르지만, 매우 조잡한 압축 알고리즘조차도 IO 바운드 문제를 제거 할 수 있습니다.

한 스레드는 지속적으로 계산 집약적 프로세스의 단계를 실행 한 다음 부분 결과를 부분 결과 큐에 추가합니다. 다른 스레드는 큐의 부분 결과를 지속적으로 제거하고 디스크에 씁니다. 큐에 대한 액세스를 동기화해야합니다. 큐는 목록과 같은 데이터 구조로 끝에 항목을 추가하고 전면에서 항목을 제거 할 수 있습니다.

응용 프로그램에 두 가지가 있습니다 스레드, 하나는 CPU이고 하나는 하드 디스크 용입니다.

CPU 스레드 푸시 데이터를 완성한 데이터를 큐로 완성한 후 하드 디스크 스레드가 데이터가 들어 오면 가져옵니다.

이런 식으로 CPU는 단지 데이터를 제거하고 다른 사람 이이 데이터를 처리 할 수있게하고 하드 드라이브는 대기열의 데이터를 참을성있게 기다립니다.

구현 현명하게, 당신은 큐를 공유 메모리 유형의 객체로 수행 할 수 있지만, 파이프는 당신이 찾고있는 것과 정확히 일할 것이라고 생각합니다. CPU는 필요할 때 단순히 파이프에 글을 씁니다. 하드 디스크 쪽에서는 파이프를 읽고 유효한 데이터가있을 때마다 거기에서 진행하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top