Tôi nghĩ rằng nút cổ chai bạn có ở đây là gấp đôi.
Tùy thuộc vào hệ điều hành và bộ điều khiển đĩa của bạn, các cuộc gọi tới f.read(2)
với f
là một tệp lớn thường được đệm hiệu quả - usually. Nói cách khác, hệ điều hành sẽ đọc một hoặc hai sector (với các sector disc thường là vài KB) ra đĩa vào bộ nhớ vì nó không đắt hơn nhiều so với việc đọc 2 byte từ tập tin đó. Các byte thừa được lưu trữ hiệu quả trong bộ nhớ đã sẵn sàng cho cuộc gọi tiếp theo để đọc tệp đó. Đừng dựa vào hành vi đó - nó có thể là nút cổ chai của bạn - nhưng tôi nghĩ có những vấn đề khác ở đây.
Tôi quan tâm nhiều hơn đến việc chuyển đổi một byte thành một cuộc gọi ngắn và đơn lẻ thành số lượng lớn. Đây là những không được lưu trữ ở tất cả. Bạn có thể giữ tất cả các quần short trong một danh sách Python của ints và chuyển đổi toàn bộ danh sách thành gumpy khi (và nếu) cần thiết. Bạn cũng có thể thực hiện một cuộc gọi duy nhất struct.unpack_from
để chuyển đổi mọi thứ trong bộ đệm so với một bộ đệm tại một thời điểm.
xem xét:
#!/usr/bin/python
import random
import os
import struct
import numpy
import ctypes
def read_wopper(filename,bytes=2,endian='>h'):
buf_size=1024*2
buf=ctypes.create_string_buffer(buf_size)
new_buf=[]
with open(filename,'rb') as f:
while True:
st=f.read(buf_size)
l=len(st)
if l==0:
break
fmt=endian[0]+str(l/bytes)+endian[1]
new_buf+=(struct.unpack_from(fmt,st))
na=numpy.array(new_buf)
return na
fn='bigintfile'
def createmyfile(filename):
bytes=165924350
endian='>h'
f=open(filename,"wb")
count=0
try:
for int in range(0,bytes/2):
# The first 32,767 values are [0,1,2..0x7FFF]
# to allow testing the read values with new_buf[value<0x7FFF]
value=count if count<0x7FFF else random.randint(-32767,32767)
count+=1
f.write(struct.pack(endian,value&0x7FFF))
except IOError:
print "file error"
finally:
f.close()
if not os.path.exists(fn):
print "creating file, don't count this..."
createmyfile(fn)
else:
read_wopper(fn)
print "Done!"
Tôi tạo ra một tập tin của quần short ngẫu nhiên ký ints của 165.924.350 byte (158,24 MB) mà comports đến 82.962.175 ký 2 byte quần short. Với tập tin này, tôi chạy read_wopper
chức năng trên và nó chạy trong:
real 0m15.846s
user 0m12.416s
sys 0m3.426s
Nếu bạn không cần quần short được NumPy, chức năng này chạy trong 6 giây. Tất cả điều này trên OS X, python 2.6.1 64 bit, 2.93 gHz Core i7, 8 GB ram. Nếu bạn thay đổi buf_size=1024*2
trong read_wopper
-buf_size=2**16
thời gian chạy là:
real 0m10.810s
user 0m10.156s
sys 0m0.651s
Vì vậy, cổ chai chính của bạn, tôi nghĩ, là byte đơn kêu gọi để giải nén - không 2 byte của bạn đọc từ đĩa. Bạn có thể muốn đảm bảo rằng các tệp dữ liệu của bạn không bị phân mảnh và nếu bạn đang sử dụng OS X mà free disc space (và here) của bạn không bị phân mảnh.
Chỉnh sửa Tôi đã đăng mã đầy đủ để tạo sau đó đọc tệp nhị phân của int. Trên iMac của tôi, tôi liên tục nhận được < 15 giây để đọc tệp ints ngẫu nhiên. Phải mất khoảng 1:23 để tạo ra kể từ khi sáng tạo là một đoạn ngắn tại một thời điểm.
Tôi nghĩ nó chậm vì 'byte = 2'. – khachik
Đọc một tập tin 150mb là sẽ được làm chậm. Bạn mong chờ điều gì? Làm thế nào chậm là nó? – Falmarri
Nó thực sự chỉ khoảng 3,5 phút (theo unix 'time') nhưng tôi có thể đọc nó trong R trong ít hơn một phút bằng cách sử dụng' readBin' – hatmatrix