Tôi nhận được một mảng 512^3 đại diện cho phân bố Nhiệt độ 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 phải biết tối thiểu, tối đa và có nghĩa là của mảng này và như tôi sẽ sớm cần phải hiểu mã Fortran anyway, tôi quyết định để cho nó một đi và đến với thói quen rất dễ dàng sau đây.Làm thế nào để có thể nhanh hơn nhiều so với thường lệ của Fortran?
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)
Điều này mất khoảng 25 giây cho mỗi tệp trên máy tôi sử dụng. Đánh tôi như là khá dài và vì vậy tôi đã đi trước và đã làm như sau trong 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 nghĩ đây chỉ là nhanh hơn tất nhiên, nhưng tôi đã thực sự thổi bay đi. Phải mất ít hơn một giây trong điều kiện giống hệt nhau. Giá trị trung bình bị lệch so với mức phát hiện thường thấy của Fortran (mà tôi cũng chạy với các phao 128 bit, vì vậy bằng cách nào đó tôi tin tưởng nó nhiều hơn) nhưng chỉ trên số có nghĩa thứ 7 hoặc hơn.
Làm thế nào để có thể quá nhanh? Tôi có nghĩa là bạn phải xem xét mọi mục nhập của một mảng để tìm các giá trị này, đúng không? Tôi đang làm điều gì đó rất ngu ngốc trong thói quen Fortran của tôi cho nó mất nhiều thời gian hơn?
EDIT:
Để trả lời các câu hỏi trong các ý kiến:
- Vâng, tôi cũng chạy thường xuyên Fortran với 32-bit và 64-bit nổi 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 nổi 128 bit. - Sử dụng phao 32 bit, giá trị trung bình của tôi bị giảm đi một chút, vì vậy độ chính xác thực sự là vấn đề.
- Tôi chạy cả hai thường trình trên các tệp khác nhau theo thứ tự khác nhau, vì vậy bộ nhớ đệm nên có công bằng trong so sánh tôi đoán?
- Tôi thực sự đã thử mở MP, nhưng để đọc từ tệp tại các vị trí khác nhau cùng một lúc. Có đọc ý kiến của bạn và câu trả lời này âm thanh thực sự ngu ngốc bây giờ và nó làm cho thói quen mất nhiều thời gian là tốt. Tôi có thể cung cấp cho nó một thử trên các hoạt động mảng nhưng có lẽ 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ờ.
EDIT 2:
tôi thực hiện những gì @Alexander Vogt và @ Casey gợi ý trong câu trả lời của họ, và nó là nhanh như numpy
nhưng bây giờ tôi có một vấn đề chính xác như @Luaan chỉ ra tôi có thể được. Sử dụng mảng phao 32 bit, giá trị trung bình tính bằng sum
là 20%. Làm
...
real,allocatable :: tmp (:,:,:)
double precision,allocatable :: tmp2(:,:,:)
...
tmp2=tmp
mean=sum(tmp2)/size(tmp)
...
Giải quyết vấn đề nhưng tăng thời gian tính toán (không phải rất 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 được cách để đọc đĩa đơn từ tập tin trực tiếp để tăng gấp đôi. Và làm thế nào để numpy
tránh điều này?
Cảm ơn tất cả sự trợ giúp từ trước tới nay.
Bạn đã thử thường trình Fortran không có nổi 128 bit chưa? Tôi không biết bất kỳ phần cứng nào thực sự hỗ trợ những phần cứng đó, vì vậy chúng phải được thực hiện trong phần mềm. – user2357112
Điều gì sẽ xảy ra nếu bạn thử phiên bản Fortran bằng một mảng (và cụ thể là sử dụng một lần đọc thay vì một tỷ)? – francescalus
Bạn có cân nhắc sử dụng toán tử mảng trong Fortran không? Sau đó, bạn có thể thử 'minval()', 'maxval()', và 'sum()'?Hơn nữa, bạn đang trộn IO với các hoạt động trong Fortran, nhưng không phải bằng Python - đó không phải là sự so sánh công bằng ;-) –