2013-10-23 2 views
1

데이터 청크가 많습니다 (~ 50GB). 내 코드에서는 다음 작업을 수행 할 수 있어야합니다.<Chunk*> 벡터를 메모리 맵핑 된 파일로 읽거나 쓰는 방법은 무엇입니까?

  1. 모든 청크를 반복적으로 반복하고 계산을 수행합니다.

  2. 반복적으로 모든 청크를 반복하고 계산을 수행합니다. 각 반복에서 방문 청크의 순서는 (가능한 한) 무작위 화됩니다.

지금까지, 나는 ( boost::serialization로 만든) 10 개 바이너리 파일에 데이터를 분할하고 반복적으로 하나씩을 읽고 계산을 수행했다. (2)에서는 무작위 순서로 10 개의 파일을 읽고 순서대로 처리하여 충분합니다.

그러나 (boost::serialization을 사용하여) 파일 중 하나를 읽는 데 시간이 오래 걸리며 속도를 높이고 싶습니다.

boost::serialization 대신 메모리 매핑 된 파일을 사용할 수 있습니까?

특히, 각 파일에 vector<Chunk*>이 있습니다. 나는 그러한 파일을 매우 빨리, 아주 빨리 읽을 수 있기를 원한다.

vector<Chunk*> 데이터 구조는 어떻게 읽고 쓸 수 있습니까? 나는 boost::interprocess::file_mapping을 보았지만 어떻게해야할지 모르겠습니다.

나는 이것을 읽었지만 메모리 매핑 된 파일에 대해서는별로 말하지 않았다. 먼저 vector<Chunk*>을 매핑 된 메모리에 저장 한 다음 청크 자체를 저장한다고 생각합니다. 그리고, vector<Chunk*>은 실제로는 offset_ptr<Chunk>*이 될 것이다. 즉, offset_ptr?

+0

128GB RAM의 가격은 약 1000 달러입니다. 그 기계가 가지고있는 RAM의 양은 얼마입니까? –

+0

하나의 5GB 청크에서 다음 작업을 수행하는 데 소요되는 시간은 얼마나됩니까? 나는 디스크 IO 문제인지 또는 CPU 문제인지를 묻는다. 빠른 계산에 따르면 평균 디스크는 1220 초에 5GB를 이동할 수 있다고합니다 (64KB 전송 및 전송 당 0.015 초 가정). –

+0

파일은 바이트의 배열이며 메모리 매핑시 가져옵니다. –

답변

1

메모리 매핑 된 파일은 다른 메모리와 마찬가지로 바이트, 리틀 엔디안 단어, 비트 또는 기타 데이터 구조로 구성 될 수있는 메모리 덩어리입니다. 이식성이 문제가된다면 (예 : 엔디안)주의가 필요합니다.

#include <cstdint> 
#include <memory> 
#include <vector> 
#include <iostream> 
#include <boost/iostreams/device/mapped_file.hpp> 

struct entry { 
    std::uint32_t a; 
    std::uint64_t b; 
} __attribute__((packed)); /* compiler specific, but supported 
           in other ways by all major compilers */ 

static_assert(sizeof(entry) == 12, "entry: Struct size mismatch"); 
static_assert(offsetof(entry, a) == 0, "entry: Invalid offset for a"); 
static_assert(offsetof(entry, b) == 4, "entry: Invalid offset for b"); 

int main(void) { 
    boost::iostreams::mapped_file_source mmap("map"); 
    assert(mmap.is_open()); 
    const entry* data_begin = reinterpret_cast<const entry*>(mmap.data()); 
    const entry* data_end = data_begin + mmap.size()/sizeof(entry); 
    for(const entry* ii=data_begin; ii!=data_end; ++ii) 
    std::cout << std::hex << ii->a << " " << ii->b << std::endl; 
    return 0; 
} 

data_begin 및 data_end 포인터가 다른 반복자와 같은 대부분의 STL의 기능을 사용할 수 있습니다

다음 코드는 좋은 출발점이 될 수 있습니다.