F #

2014-06-24 5 views
2

의 특정 위치에서 이진 파일에서 정수를 읽는 성능 문제 오늘 아침에 내 파이썬 코드가 내 F # 버전보다 속도가 느린 이유는 무엇입니까? here하지만 F # 버전을 더 빨리 만들 수 있는지 궁금합니다. 32 비트 정수를 가진 이진 파일에서 고유 인덱스의 정렬 된 목록을 읽는 아래 코드의 더 빠른 버전을 어떻게 만들 수 있습니까? BinaryReader를 기반으로하는 방법과 MemoryMappedFile (and some more on Github)을 기반으로하는 방법 중 하나를 사용하여 2 가지 방법을 시도했습니다. 비교를 위해F #

module SimpleRead    
    let readValue (reader:BinaryReader) cellIndex = 
     // set stream to correct location 
     reader.BaseStream.Position <- cellIndex*4L 
     match reader.ReadInt32() with 
     | Int32.MinValue -> None 
     | v -> Some(v) 

    let readValues fileName indices = 
     use reader = new BinaryReader(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) 
     // Use list or array to force creation of values (otherwise reader gets disposed before the values are read) 
     let values = List.map (readValue reader) (List.ofSeq indices) 
     values 

module MemoryMappedSimpleRead = 

    open System.IO.MemoryMappedFiles 

    let readValue (reader:MemoryMappedViewAccessor) offset cellIndex = 
     let position = (cellIndex*4L) - offset 
     match reader.ReadInt32(position) with 
     | Int32.MinValue -> None 
     | v -> Some(v) 

    let readValues fileName indices = 
     use mmf = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open) 
     let offset = (Seq.min indices) * 4L 
     let last = (Seq.max indices) * 4L 
     let length = 4L+last-offset 
     use reader = mmf.CreateViewAccessor(offset, length, MemoryMappedFileAccess.Read) 
     let values = (List.ofSeq indices) |> List.map (readValue reader offset) 
     values 

여기

import numpy as np 

def convert(v): 
    if v <> -2147483648: 
     return v 
    else: 
     return None 

def read_values(filename, indices): 
    values_arr = np.memmap(filename, dtype='int32', mode='r') 
    return map(convert, values_arr[indices]) 

가 업데이트 내가 여기 전에 한 말에 반하는에서 , 내 파이썬은에 여전히 F # 버전의 다음 많이 느리지 만 인해 내 최신 NumPy와 버전입니다 내 파이썬 테스트에서 오류가 발생했습니다. BinaryReader 또는 MemoryMappedFile에 대한 충분한 지식이있는 사람을 위해이 질문을 남겨 두십시오.

+0

자신이 할 수있는 코드를 프로파일 링하지 않으면 아무도이 권한에 정식으로 응답 할 수 없습니다. – Daniel

+0

프로파일 링을 사용하면 지금까지만 갈 수 있습니다. 내 원래 파이썬 버전에서 프로파일 링과 numpy 또는 hdf5 솔루션을 찾지 못했을 것입니다. .NET에서 이진 파일 및 메모리 매핑 된 파일을 읽는 데별로 경험이 없기 때문에 유사한 성능 향상이 가능한지 궁금합니다. – Samuel

+4

numpy와 .NET memmap 버전 간의 성능 차이는 무엇입니까? F #에서 memmap 버전이 가장 빠릅니까? – Daniel

답변

1

reader.BaseStream.Position 대신 reader.BaseStream.Seek를 사용하여 30 % 더 빠른 SimpleReader를 얻을 수있었습니다. 나는 또한리스트를 배열로 대체했는데 이것은 많이 변하지 않았다.

내 간단한 독자의 전체 코드는 이제 : 다른 언어

open System 
open System.IO 

let readValue (reader:BinaryReader) cellIndex = 
    // set stream to correct location 
    reader.BaseStream.Seek(int64 (cellIndex*4), SeekOrigin.Begin) |> ignore 
    match reader.ReadInt32() with 
    | Int32.MinValue -> None 
    | v -> Some(v) 

let readValues indices fileName = 
    use reader = new BinaryReader(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) 
    // Use list or array to force creation of values (otherwise reader gets disposed before the values are read) 
    let values = Array.map (readValue reader) indices 
    values 

전체 코드와 버전 GitHub 있습니다.