Я получаю массив 512 ^ 3, представляющий распределение температуры от моделирования (написанное на языке Fortran). Массив хранится в двоичном файле размером около 1/2G. Мне нужно знать минимальный, максимальный и средний из этого массива, и поскольку мне скоро понадобится понять код 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)
Это занимает около 25 секунд на файл на машине, которую я использую. Это показалось мне довольно длинным, поэтому я пошел дальше и сделал следующее на 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)
Теперь я ожидал, что это будет быстрее, но я действительно сдулся. В то же время требуется меньше секунды. Среднее отклоняется от одного моего подпрограммы "Fortran" (который я также запускал с 128-битными поплавками, поэтому я как-то доверяю ему больше), но только на 7-й значащей цифре или около того.
Как numpy может быть настолько быстрым? Я имею в виду, что вы должны смотреть на каждую запись массива, чтобы найти эти значения, не так ли? Я делаю что-то очень глупо в моей программе Fortran, чтобы она занимала намного больше времени?
EDIT:
Чтобы ответить на вопросы в комментариях:
- Да, я также запускал подпрограмму Fortran с 32-битными и 64-битными поплавками, но не влиял на производительность.
 -  Я использовал 
iso_fortran_env, который обеспечивает 128-битные поплавки. - Используя 32-битные поплавки, мое среднее значение довольно велико, поэтому точность действительно является проблемой.
 - Я запускал обе процедуры в разных файлах в другом порядке, поэтому кеширование должно быть справедливым в сравнении, я думаю?
 - Я на самом деле пробовал открытый MP, но читал из файла на разных позициях одновременно. Прочитав ваши комментарии и ответы, это звучит действительно глупо сейчас, и это заставило процедуру заняться намного дольше. Я мог бы дать ему попробовать массивные операции, но, возможно, это даже не понадобится.
 - Файлы на самом деле размером 1/2G, это была опечатка, спасибо.
 - Теперь я попробую реализацию массива.
 
ИЗМЕНИТЬ 2:
Я реализовал то, что @Alexander Vogt и @casey предложили в своих ответах, и это так же быстро, как numpy, но теперь у меня есть проблема с точностью, которую, как заметил @Luaan, я могу получить. Используя 32-битный массив с плавающей точкой, среднее значение, вычисленное на sum, составляет 20%. Выполнение
...
real,allocatable :: tmp (:,:,:)
double precision,allocatable :: tmp2(:,:,:)
...
tmp2=tmp
mean=sum(tmp2)/size(tmp)
...
Решает проблему, но увеличивает вычислительное время (не очень, но заметно).
Есть ли лучший способ обойти эту проблему? Я не мог найти способ прочитать синглы из файла непосредственно в парном разряде.
И как numpy избежать этого?
Спасибо за всю помощь до сих пор.