Построение графиков тысяч файлов с помощью python


У меня в порядке, или 10^5 двоичных файлов, которые я читал в for цикл с включает в fromfile и земельный участок с pyplot по imshow. Каждый файл занимает около минуты, чтобы прочитать и построить график.

Есть ли способ ускорить события?

Вот некоторый псевдокод, чтобы объяснить мою ситуацию:

#!/usr/bin/env python

import numpy as np
import matplotlib as mpl
mpl.use('Agg')

import matplotlib.pyplot as plt

nx = 1200 ; ny = 1200

fig, ax = plt.subplots()
ax.set_xlabel('x')
ax.set_ylabel('y')

for f in files:
  data = np.fromfile(open(f,'rb'), dtype=float32, count=nx*ny)
  data.resize(nx,ny)
  im = ax.imshow(data)
  fig.savefig(f+'.png', dpi=300, bbox_inches='tight')
  im.remove()
Я нашел последний шаг решающим, чтобы память не взорвалась .
2 2

2 ответа:

Поскольку количество изображений очень велико и вы используете imshow, я бы предложил другой подход.

  1. создайте выходной файл с требуемыми размерами и пустым изображением (любой цвет делает это до тех пор, пока он не совпадает с цветом корешка)
  2. сохраните рисунок в template.png
  3. загрузить template.png с помощью scipy.ndimage.imread
  4. загрузите данные изображения в массив
  5. скрытие данных в цвета с помощью цветовых карт
  6. масштабируйте изображение в соответствии с пикселем размеры шаблона (scipy.ndimage.zoom)
  7. скопируйте пиксельные данные в шаблон
  8. сохраните полученное изображение с помощью scipy.ndimage.save
  9. повторите шаги 4-8 столько раз, сколько вам нужно

Это позволит обойти много рендеринга. Некоторые комментарии:

    Шаг 1 может занять довольно много времени (особенно анти-псевдоним может потребовать внимания, полезно иметь резкую черно-белую границу по краям шипов)
  • Если Шаг 4 медленный (я не делаю поймите почему), попробуйте numpy.memmap
  • Если вы можете, попробуйте использовать цветовую карту, которая может быть получена с помощью простых арифметических операций с данными (например, оттенки серого, оттенки серого с гаммой и т. д.), то вы можете сделать шаг 5 быстрее
  • Если вы можете жить с изображениями, где ваши данные не масштабируются (т. е. область, используемая исходным imshow , равна 1200x1200), вы можете избавиться от медленной операции масштабирования (Шаг 6); это также помогает, если вы можете уменьшить размер на целое число
  • Если вам нужно пересчитать изображения в шаге 6, вы также можете проверить функции в модуле cv2 (OpenCV), они могут быть быстрее, чем более общие функции в scipy.ndimage
С точки зрения производительности самыми медленными операциями являются 5, 6 и 9. Я бы ожидал, что функция будет способна обрабатывать, возможно, десять массивов в секунду. Кроме того, дисковый ввод-вывод начнет быть ограничивающим фактором. Если шаг обработки является ограничивающим фактором, я бы просто запустил четыре (предполагая, что есть четыре ядра) копии сценария, каждая копия имея доступ к другому набору изображений 2.5 x 10^4. С SSD-диском это не должно вызывать катастроф ввода-вывода.

Только профилирование скажет, хотя.

Странно, после перезагрузки, решение, к которому я обычно не прибегаю, время чтения сокращается до ~0,002 секунды (в среднем) на файл, а время рендеринга составляет ~0,02 секунды. Сохранение файла .png занимает ~2,6 секунды, так что в целом каждый кадр занимает около 2,7 секунды.

Я воспользовался советом @DrV,

...Я бы просто запустил четыре (предполагая, что есть четыре ядра) копии сценария,каждая копия имеет доступ к другому набору изображений 2.5 x 10^4. С SSD-диском это не должно вызывать поиск ввода-вывода катастрофы.

Разбил список файлов на 8 подсписков и запустил 8 экземпляров моего скрипта.

Комментарий@DrV

Кроме того, ваше время чтения 0.002 С для чтения файла 5.7 MB не кажется реалистичным, если файл не находится в кэше оперативной памяти, так как это указывает на скорость чтения диска 2.8 Гб/с. (быстрые SSDs могут достигать 500 МБ/с.)

Заставил меня проверить скорость чтения / записи на моем ноутбуке (MacBookPro10, 1). Я использовал следующий код для создания 1000 файлов с 1200 * 1200 случайных поплавков (4 байта), так что каждый файл составляет 5,8 МБ (1200*1200*4 = 5 760 000 байт), а затем считывать их один за другим, синхронизируя процесс. Код запускается с терминала и никогда не занимает более 50 Мбайт или памяти (довольно много для хранения только одного массива данных 5,8 Мбайт в памяти, не так ли?).

Код:

#!/usr/bin/env ipython

import os
from time import time
import numpy as np

temp = 'temp'
if not os.path.exists(temp):
    os.makedirs(temp)
    print 'temp dir created'
os.chdir(temp)

nx = ny = 1200
nof = 1000
print '\n*** Writing random data to files ***\n'
t1 = time(); t2 = 0; t3 = 0
for i in range(nof):
    if not i%10:
        print str(i),
    tt = time()
    data = np.array(np.random.rand(nx*ny), dtype=np.float32)
    t2 += time()-tt
    fn = '%d.bin' %i
    tt = time()
    f = open(fn, 'wb')
    f.write(data)
    f.close
    t3 += time()-tt
print '\n*****************************'
print 'Total time: %f seconds' %(time()-t1)
print '%f seconds (on average) per random data production' %(t2/nof)
print '%f seconds (on average) per file write' %(t3/nof)

print '\n*** Reading random data from files ***\n'
t1 = time(); t3 = 0
for i,fn in enumerate(os.listdir('./')):
    if not i%10:
        print str(i),
    tt = time()
    f = open(fn, 'rb')
    data = np.fromfile(f)
    f.close
    t3 += time()-tt
print '\n*****************************'
print 'Total time: %f seconds' %(time()-t1)
print '%f seconds (on average) per file read' %(t3/(i+1))

# cleen up:
for f in os.listdir('./'):
    os.remove(f)
os.chdir('../')
os.rmdir(temp)

Результат:

temp dir created

*** Writing random data to files ***

0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 360 370 380 390 400 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640 650 660 670 680 690 700 710 720 730 740 750 760 770 780 790 800 810 820 830 840 850 860 870 880 890 900 910 920 930 940 950 960 970 980 990 
*****************************
Total time: 25.569716 seconds
0.017786 seconds (on average) per random data production
0.007727 seconds (on average) per file write

*** Reading random data from files ***

0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 360 370 380 390 400 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640 650 660 670 680 690 700 710 720 730 740 750 760 770 780 790 800 810 820 830 840 850 860 870 880 890 900 910 920 930 940 950 960 970 980 990 
*****************************
Total time: 2.596179 seconds
0.002568 seconds (on average) per file read