今天早上我问here https://stackoverflow.com/questions/24381090/performance-issue-with-reading-integers-from-a-binary-file-at-specific-locations为什么我的 Python 代码比我的 F# 版本慢很多,但我想知道 F# 版本是否可以变得更快。我有什么想法可以创建以下代码的更快版本,从具有 32 位整数的二进制文件中读取唯一索引的排序列表?请注意,我尝试了两种方法,一种基于 BinaryReader,另一种基于 MemoryMappedFile (以及 Github 上的更多内容 https://github.com/samuelbosch/blogbits/blob/master/geosrc/AsciiToBin.fsx).
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
为了进行比较,这里是我最新的 numpy 版本
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])
Update与我之前所说的相反,我的 python 仍然比 F# 版本慢很多,但由于我的 python 测试中的错误,它看起来并非如此。
将此问题留在这里,以防对 BinaryReader 或 MemoryMappedFile 有深入了解的人知道一些改进。