Tôi nhận được một mảng 512 ^ 3 biểu thị sự phân bố Nhiệt độ từ một mô phỏng (được viết bằng Fortran). Mảng được lưu trữ trong một tệp nhị phân có kích thước khoảng 1 / 2G. Tôi cần biết mức tối thiểu, tối đa và trung bình của mảng này và vì tôi sẽ sớm hiểu mã Fortran, tôi quyết định thử và nghĩ ra quy trình rất dễ dàng sau đây.
integer gridsize,unit,j
real mini,maxi
double precision mean
gridsize=512
unit=40
open(unit=unit,file='T.out',status='old',access='stream',&
form='unformatted',action='read')
read(unit=unit) tmp
mini=tmp
maxi=tmp
mean=tmp
do j=2,gridsize**3
read(unit=unit) tmp
if(tmp>maxi)then
maxi=tmp
elseif(tmp<mini)then
mini=tmp
end if
mean=mean+tmp
end do
mean=mean/gridsize**3
close(unit=unit)
Quá trình này mất khoảng 25 giây cho mỗi tệp trên máy tôi sử dụng. Điều đó khiến tôi cảm thấy khá lâu và vì vậy tôi đã tiếp tục và thực hiện những việc sau bằng Python:
import numpy
mmap=numpy.memmap('T.out',dtype='float32',mode='r',offset=4,\
shape=(512,512,512),order='F')
mini=numpy.amin(mmap)
maxi=numpy.amax(mmap)
mean=numpy.mean(mmap)
Bây giờ, tôi đã mong đợi điều này tất nhiên sẽ nhanh hơn, nhưng tôi đã thực sự bị thổi bay. Nó mất ít hơn một giây trong các điều kiện giống hệt nhau. Giá trị trung bình khác với giá trị mà tôi thường xuyên tìm thấy trong Fortran (mà tôi cũng đã chạy với phao 128 bit, vì vậy bằng cách nào đó tôi tin tưởng nó hơn) nhưng chỉ ở chữ số có nghĩa thứ 7 hoặc lâu hơn.
Làm thế nào mà numpy có thể nhanh như vậy? Ý tôi là bạn phải xem mọi mục nhập của một mảng để tìm những giá trị này, phải không? Tôi có đang làm điều gì đó rất ngu ngốc trong thói quen Fortran của mình để nó mất nhiều thời gian hơn không?
BIÊN TẬP:
Để trả lời các câu hỏi trong phần bình luận:
- Có, tôi cũng đã chạy quy trình Fortran với phao 32 bit và 64 bit nhưng nó không ảnh hưởng đến hiệu suất.
- Tôi đã sử dụng
iso_fortran_env
cung cấp phao 128 bit. - Mặc dù vậy, việc sử dụng phao 32-bit có nghĩa là hơi sai, vì vậy độ chính xác thực sự là một vấn đề.
- Tôi đã chạy cả hai quy trình trên các tệp khác nhau theo thứ tự khác nhau, do đó, bộ nhớ đệm lẽ ra phải công bằng khi so sánh?
- Tôi thực sự đã thử mở MP, nhưng để đọc từ tệp ở các vị trí khác nhau cùng một lúc. Sau khi đọc các bình luận và câu trả lời của bạn, điều này nghe có vẻ thực sự ngu ngốc và nó cũng làm cho quy trình mất nhiều thời gian hơn. Tôi có thể thử các phép toán mảng nhưng có lẽ điều đó thậm chí sẽ không cần thiết.
- Các tệp thực sự có kích thước 1 / 2G, đó là lỗi đánh máy, Cảm ơn.
- Tôi sẽ thử triển khai mảng ngay bây giờ.
CHỈNH SỬA 2:
Tôi đã triển khai những gì @Alexander Vogt và @casey đề xuất trong câu trả lời của họ và nó nhanh như numpy
vậy nhưng bây giờ tôi gặp vấn đề về độ chính xác như @Luaan đã chỉ ra mà tôi có thể gặp phải. Sử dụng mảng float 32 bit, giá trị trung bình được tính bằng giảm sum
20%. Đang làm
...
real,allocatable :: tmp (:,:,:)
double precision,allocatable :: tmp2(:,:,:)
...
tmp2=tmp
mean=sum(tmp2)/size(tmp)
...
Giải quyết vấn đề nhưng làm tăng thời gian tính toán (không quá nhiều, nhưng đáng chú ý). Có cách nào tốt hơn để giải quyết vấn đề này không? Tôi không thể tìm thấy cách đọc đĩa đơn từ tệp trực tiếp đến đĩa đôi. Và làm thế nào để numpy
tránh điều này?
Cảm ơn tất cả sự giúp đỡ cho đến nay.