Большой сюжет: ~ 20 миллионов образцов, гигабайты данных - PullRequest
60 голосов
/ 02 мая 2011

У меня проблема (с моей оперативной памятью): она не может содержать данные, которые я хочу построить. У меня достаточно места на HD. Есть ли какое-либо решение, чтобы избежать "затенения" моего набора данных?

Конкретно я имею дело с цифровой обработкой сигналов, и мне приходится использовать высокую частоту дискретизации. Мой фреймворк (GNU Radio) сохраняет значения (чтобы не использовать слишком много места на диске) в двоичном виде. Я распаковываю это. После этого мне нужно построить. Мне нужен сюжет масштабируемый и интерактивный. И это проблема.

Есть ли потенциал для оптимизации этого или другого программного обеспечения / языка программирования (например, R или около того), который может обрабатывать большие наборы данных? На самом деле я хочу гораздо больше данных на моих графиках. Но у меня нет опыта работы с другими программами. GNUplot терпит неудачу, с подобным подходом к следующему. Я не знаю R (джет).

import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import struct

"""
plots a cfile

cfile - IEEE single-precision (4-byte) floats, IQ pairs, binary
txt - index,in-phase,quadrature in plaintext

note: directly plotting with numpy results into shadowed functions
"""

# unpacking the cfile dataset
def unpack_set(input_filename, output_filename):
    index = 0   # index of the samples
    output_filename = open(output_filename, 'wb')

    with open(input_filename, "rb") as f:

        byte = f.read(4)    # read 1. column of the vector

        while byte != "":
        # stored Bit Values
            floati = struct.unpack('f', byte)   # write value of 1. column to a variable
            byte = f.read(4)            # read 2. column of the vector
            floatq = struct.unpack('f', byte)   # write value of 2. column to a variable
            byte = f.read(4)            # next row of the vector and read 1. column
            # delimeter format for matplotlib 
            lines = ["%d," % index, format(floati), ",",  format(floatq), "\n"]
            output_filename.writelines(lines)
            index = index + 1
    output_filename.close
    return output_filename.name

# reformats output (precision configuration here)
def format(value):
    return "%.8f" % value            

# start
def main():

    # specify path
    unpacked_file = unpack_set("test01.cfile", "test01.txt")
    # pass file reference to matplotlib
    fname = str(unpacked_file)
    plt.plotfile(fname, cols=(0,1)) # index vs. in-phase

    # optional
    # plt.axes([0, 0.5, 0, 100000]) # for 100k samples
    plt.grid(True)
    plt.title("Signal-Diagram")
    plt.xlabel("Sample")
    plt.ylabel("In-Phase")

    plt.show();

if __name__ == "__main__":
    main()

Что-то вроде plt.swap_on_disk () может кэшировать содержимое моего SSD;)

Ответы [ 6 ]

67 голосов
/ 02 мая 2011

Таким образом, ваши данные не так велики, и тот факт, что у вас возникли проблемы с их составлением, указывает на проблемы с инструментами. Matplotlib .... не так хорошо. У него много опций, и вывод в порядке, но это огромная проблема с памятью, и она в основном предполагает, что ваши данные малы. Но есть и другие варианты.

Итак, в качестве примера, я сгенерировал 20-миллиметровый файл точек данных 'bigdata.bin', используя следующее:

#!/usr/bin/env python
import numpy
import scipy.io.numpyio

npts=20000000
filename='bigdata.bin'

def main():
    data = (numpy.random.uniform(0,1,(npts,3))).astype(numpy.float32)
    data[:,2] = 0.1*data[:,2]+numpy.exp(-((data[:,1]-0.5)**2.)/(0.25**2))
    fd = open(filename,'wb')
    scipy.io.numpyio.fwrite(fd,data.size,data)
    fd.close()

if __name__ == "__main__":
    main()

Это создает файл размером ~ 229 МБ, который не так уж и велик; но вы заявили, что хотите перейти к файлам еще большего размера, поэтому в конечном итоге вы достигнете пределов памяти.

Давайте сначала сосредоточимся на неинтерактивных сюжетах. Первое, что нужно понять, это то, что векторные графики с глифами в каждой точке будут катастрофой - для каждой из 20 точек M, большинство из которых в любом случае будут перекрываться, пытаясь сделать маленькие крестики или круги или что-то еще быть диастером, генерировать огромные файлы и тратить много времени. Это, я думаю, то, что тонет matplotlib по умолчанию.

У Gnuplot нет проблем с этим:

gnuplot> set term png
gnuplot> set output 'foo.png'
gnuplot> plot 'bigdata.bin' binary format="%3float32" using 2:3 with dots

gnuplot

И даже Matplotlib можно вести себя с некоторой осторожностью (выбирая растровую часть и используя пиксели для разметки точек):

#!/usr/bin/env python
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

datatype=[('index',numpy.float32), ('floati',numpy.float32), 
        ('floatq',numpy.float32)]
filename='bigdata.bin'

def main():
    data = numpy.memmap(filename, datatype, 'r') 
    plt.plot(data['floati'],data['floatq'],'r,')
    plt.grid(True)
    plt.title("Signal-Diagram")
    plt.xlabel("Sample")
    plt.ylabel("In-Phase")
    plt.savefig('foo2.png')

if __name__ == "__main__":
    main()  

matplotlib

Теперь, если вам нужен интерактив, вам придется складывать данные в график и увеличивать их на лету. Я не знаю каких-либо инструментов Python, которые помогут вам сделать это случайно.

С другой стороны, построение больших данных - довольно распространенная задача, и есть инструменты, подходящие для этой задачи. Paraview - мой личный фаворит, а VisIt - другой. Они оба в основном предназначены для трехмерных данных, но Paraview, в частности, также работает и с 2D, и очень интерактивен (и даже имеет интерфейс сценариев Python). Единственная хитрость заключается в том, чтобы записать данные в формат файла, который Paraview может легко прочитать.

12 голосов
/ 02 мая 2011

Вы, безусловно, можете оптимизировать чтение вашего файла: вы можете напрямую прочитать его в массив NumPy, чтобы использовать сырую скорость NumPy.У вас есть несколько вариантов.Если ОЗУ является проблемой, вы можете использовать memmap , которая хранит большую часть файла на диске (а не в ОЗУ):

# Each data point is a sequence of three 32-bit floats:
data = np.memmap(filename, mode='r', dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])

Если ОЗУ не является проблемой, вы можетепоместите весь массив в ОЗУ с помощью fromfile :

data = np.fromfile(filename, dtype=[('index', 'float32'), ('floati','float32'), ('floatq', 'float32')])

Построение графика может быть затем выполнено с помощью обычной функции plot(*data) Matplotlib, возможно, с помощью метода «увеличения», предложенного в другом решении.

11 голосов
/ 15 марта 2014

Более поздний проект имеет большой потенциал для больших наборов данных: Боке , который был создан с учетом именно этого .

Фактически, только данные, относящиеся к масштабу графика, отправляются на серверную часть дисплея. Этот подход намного быстрее, чем подход Matplotlib.

7 голосов

Обзор программного обеспечения для интерактивных построений с открытым исходным кодом с эталонным графиком рассеяния в 10 миллионов точек на Ubuntu 18.10

Вдохновленный сценарием использования, описанным по адресу: https://stats.stackexchange.com/questions/376361/how-to-find-the-sample-points-that-have-statistically-meaningful-large-outlier-r Я провел сравнительный анализ нескольких реализаций со следующими очень простыми и наивными данными по прямой линии на 10 миллионов точек:

i=0;
while [ "$i" -lt 10000000 ]; do
  echo "$i,$((2 * i)),$((4 * i))"; i=$((i + 1));
done > 10m.csv

Первые несколько строк 10m.csv выглядят так:

0,0,0
1,2,4
2,4,8
3,6,12
4,8,16

По сути, я хотел:

  • сделать XY-диаграмму рассеяния многомерных данных, возможно, с Z в качестве цвета точки
  • в интерактивном режиме выберите несколько интересных точек
  • Просмотрите все размеры выбранных точек, чтобы попытаться понять, почему они являются выбросами в XY-разбросе

Тесты проводились в Ubuntu 18.10, на ноутбуке ThinkPad P51 с процессором Intel Core i7-7820HQ (4 ядра / 8 потоков), 2x оперативной памятью Samsung M471A2K43BB1-CRC (2x 16 ГБ), графическим процессором NVIDIA Quadro M1200 4 ГБ GDDR5.

Сводка результатов

Это то, что я наблюдал, учитывая мой очень специфический вариант использования теста и то, что я впервые использую многие из рассмотренных программ:

Обрабатывает ли он 10 миллионов баллов:

VisIt       Yes
Paraview    Barely
Mayavi      Yes
gnuplot     Barely on non-interactive mode.
matplotlib  No

Много ли у него функций:

VisIt       Yes, 2D and 3D, focus on interactive.
Paraview    Same as above, a bit less 2D features maybe.
Mayavi      3D only, good interactive and scripting support, but more limited features.
gnuplot     Lots of features, but limited in interactive mode.
matplotlib  Same as above.

Хорошо ли выглядит графический интерфейс (не учитывая хорошую производительность):

VisIt       No
Paraview    Very
Mayavi      OK
gnuplot     OK
matplotlib  OK

Визит 2,13,3

Сайт: https://wci.llnl.gov/simulation/computer-codes/visit

Лицензия: BSD

Разработано Ливерморской национальной лабораторией им. Лоуренса , которая является лабораторией Национального управления по ядерной безопасности , так что вы можете себе представить, что 10 миллионов баллов ничего не изменит, если я смогу заставить их работать.

Установка: нет пакета Debian, просто загрузите двоичные файлы Linux с веб-сайта. Работает без установки. Смотрите также: https://askubuntu.com/questions/966901/installing-visit

На основе VTK , которая является базовой библиотекой, которую используют многие графические программы с высокой производительностью. Написано в C.

После 3 часов игры с пользовательским интерфейсом, я все заработал, и это помогло решить мой сценарий использования, как описано по адресу: https://stats.stackexchange.com/questions/376361/how-to-find-the-sample-points-that-have-statistically-meaningful-large-outlier-r

Вот как это выглядит на тестовых данных этого поста:

enter image description here

и увеличение с некоторыми кирками:

enter image description here

и вот окно выбора:

enter image description here

С точки зрения производительности, VisIt была очень хорошей: каждая графическая операция либо занимала небольшое количество времени, либо выполнялась незамедлительно, и я думаю, что она может легко обрабатывать гораздо больше данных. Когда мне пришлось ждать, оно показывает «обработку» сообщения с процентом оставшейся работы, и графический интерфейс не зависает.

Так как 10 миллионов точек работали так хорошо, я также пробовал 100 миллионов очков (файл CSV 2,7 ГБ), но он упал / перешел в странное состояние, к сожалению, я наблюдал это в htop, поскольку 4 потока VisIt заняли все мои 16 ГБ ОЗУ и скорее всего умерла из-за сбоя malloc.

Первое начало было немного болезненным:

  • многие из дефолтов кажутся ужасными, если вы не инженер по атомной бомбе? Например.:
    • размер точки по умолчанию 1px (запутывается от пыли на моем мониторе)
    • масштаб осей от 0,0 до 1,0: Как отобразить фактические значения числа осей в программе построения графиков Визит вместо дробей от 0,0 до 1,0?
    • многооконные настройки, неприятные множественные всплывающие окна при выборе точек данных
    • показывает ваше имя пользователя и график (удалите с помощью "Controls"> "Аннотация"> "Информация о пользователе")
    • автоматическое позиционирование по умолчанию плохое: легенда конфликтует с осями, не может найти автоматизацию заголовка, поэтому пришлось добавить метку и переместить все вручную
  • функций просто много, поэтому может быть сложно найти то, что вы хотите
  • руководство было очень полезным, , но это мамонт на 386 страницах, зловеще датированный «октябрь 2005 г., версия 1.5». Интересно, использовали ли они это для разработки Trinity ! , и это красивый Сфинкс HTML , созданный сразу после того, как я первоначально ответил на этот вопрос
  • нет пакета Ubuntu. Но встроенные двоичные файлы просто работали.

Я отношу эти проблемы к:

  • он существует уже очень давно и использует некоторые устаревшие идеи графического интерфейса
  • Вы не можете просто щелкнуть по элементам графика, чтобы изменить их (например, оси, заголовок и т. Д.), И есть много функций, поэтому найти тот, который вы ищете, немного сложно

Мне также нравится, как немного инфраструктуры LLNL просачивается в это репо. Смотрите, например, docs / OfficeHours.txt и другие файлы в этом каталоге! Я извиняюсь за Брэда, который является "парнем в понедельник утром"! Да, и пароль для автоответчика - "Убить Эда", не забывайте это.

Paraview 5.4.1

Сайт: https://www.paraview.org/

Лицензия: BSD

Установка:

sudo apt-get install paraview

Разработано Sandia National Laboratories , которая является еще одной лабораторией NNSA, поэтому мы снова ожидаем, что она легко обработает данные. Также VTK основан и написан на C ++, что было еще более перспективно.

Однако я был разочарован: по некоторым причинам, 10 миллионов очков сделали GUI очень медленным и безразличным.

Я в порядке с контролируемым, хорошо разрекламированным моментом "Я сейчас работаю, подожди немного", но GUI зависает, когда это происходит? Неприемлемо.

htop показал, что Paraview использовал 4 потока, но ни процессор, ни память не были исчерпаны.

С точки зрения графического интерфейса, Paraview очень красивый и современный, намного лучше, чем VisIt, когда он не заикается. Вот это для подсчета очков:

enter image description here

и вот электронная таблица с выбором точки вручную:

enter image description here

Другим недостатком является то, что Paraview чувствовал недостаток функций по сравнению с VisIt, например ::111172

Mayavi 4.6.2

Сайт: https://github.com/enthought/mayavi

Разработано: Enthought

Установка:

sudo apt-get install libvtk6-dev
python3 -m pip install -u mayavi PyQt5

VTK Python один.

Mayavi, кажется, очень сосредоточен на 3D, я не мог найти, как сделать 2D-графики в нем, поэтому он, к сожалению, не подходит для моего случая использования.

Просто для проверки производительности, однако, я адаптировал пример из: https://docs.enthought.com/mayavi/mayavi/auto/example_scatter_plot.html для 10 миллионов точек, и он работает нормально, без задержки:

import numpy as np
from tvtk.api import tvtk
from mayavi.scripts import mayavi2

n = 10000000
pd = tvtk.PolyData()
pd.points = np.linspace((1,1,1),(n,n,n),n)
pd.verts = np.arange(n).reshape((-1, 1))
pd.point_data.scalars = np.arange(n)

@mayavi2.standalone
def main():
   from mayavi.sources.vtk_data_source import VTKDataSource
   from mayavi.modules.outline import Outline
   from mayavi.modules.surface import Surface
   mayavi.new_scene()
   d = VTKDataSource()
   d.data = pd
   mayavi.add_source(d)
   mayavi.add_module(Outline())
   s = Surface()
   mayavi.add_module(s)
   s.actor.property.trait_set(representation='p', point_size=1)
main()

Выход:

enter image description here

Однако я не смог увеличить масштаб достаточно, чтобы увидеть отдельные точки, ближняя трехмерная плоскость была слишком далеко. Может быть, есть способ?

Одна из замечательных особенностей Mayavi заключается в том, что разработчики приложили немало усилий, чтобы вы могли красиво запускать и настраивать GUI из скрипта Python, во многом как Matplotlib и gnuplot. Кажется, что это также возможно в Paraview, но документы, по крайней мере, не так хороши.

Как правило, он не такой особенный, как VisIt / Paraview. Например, я не могу напрямую загрузить CSV из графического интерфейса: Как загрузить файл CSV из графического интерфейса Mayavi?

Gnuplot

Сайт: http://www.gnuplot.info/

gnuplot действительно удобен, когда мне нужно идти быстро и грязно, и это всегда первое, что я пробую.

Установка:

sudo apt-get install gnuplot

Для неинтерактивного использования он может достаточно хорошо обрабатывать 10 млн. Точек:

#!/usr/bin/env gnuplot
set terminal png size 1024,1024
set output "gnuplot.png"
set key off
set datafile separator ","
plot "10m.csv" using 1:2:3 palette

, который закончился через 7 секунд:

enter image description here

Но если я попытаюсь перейти на интерактив с

#!/usr/bin/env gnuplot
set terminal wxt size 1024,1024
set key off
set datafile separator ","
plot "10m.csv" using 1:2:3 palette

и

gnuplot -persist main.gnuplot

тогда начальный рендер и масштабирование кажутся слишком вялыми. Я даже не вижу линию выделения прямоугольника!

Также обратите внимание, что для моего случая использования мне нужно было использовать гипертекстовые метки, как в:

plot "10m.csv" using 1:2:3 with labels hypertext

но была ошибка производительности с функцией надписей, в том числе для неинтерактивного рендеринга.Но я сообщил об этом, и Итан решил это за один день: https://groups.google.com/forum/#!topic/comp.graphics.apps.gnuplot/qpL8aJIi9ZE

Matplotlib 1.5.1, numpy 1.11.1, Python 3.6.7

Веб-сайт:https://matplotlib.org/

Matplotlib - это то, что я обычно пробую, когда мой скрипт gnuplot начинает становиться слишком безумным.

numpy.loadtxt один занял около 10 секунд, поэтому я знал, что это не будет хорошо:

#!/usr/bin/env python3

import numpy
import matplotlib.pyplot as plt

x, y, z = numpy.loadtxt('10m.csv', delimiter=',', unpack=True)
plt.figure(figsize=(8, 8), dpi=128)
plt.scatter(x, y, c=z)
# Non-interactive.
#plt.savefig('matplotlib.png')
# Interactive.
plt.show()

Сначала неинтерактивная попытка дала хороший результат, но заняла 3 минуты и 55 секунд ...

Затем интерактивная попытка заняла много времени при первоначальном рендеринге и увеличении.,Не используется:

enter image description here

Обратите внимание, что на этом скриншоте выбор увеличения, который должен немедленно увеличиваться и исчезать, оставался на экране долгое время, пока он ждалувеличить, чтобы вычислить!

Мне пришлось закомментировать plt.figure(figsize=(8, 8), dpi=128), чтобы интерактивная версия работала по какой-то причине, иначе она взорвалась:

RuntimeError: In set_size: Could not set the fontsize
7 голосов
/ 02 мая 2011

Я бы предложил что-то немного сложное, но это должно сработать: построить свой график с разными разрешениями, для разных диапазонов.

Вспомните, например, Google Планета Земля. Если вы увеличите масштаб до максимального уровня, чтобы охватить всю планету, разрешение будет самым низким. При увеличении изображения меняются на более детальные, но только на область, на которую вы увеличиваете.

Так что в основном для вашего графика (это 2D? 3D? Я предполагаю, что это 2D), я предлагаю вам построить один большой график, который охватывает весь диапазон [0, n] с низким разрешением, 2 меньших графика, которые покрывают [ 0, n / 2] и [n / 2 + 1, n] с удвоенным разрешением большого, 4 меньших графика, которые охватывают [0, n / 4] ... [3 * n / 4 + 1, n ] с удвоенным разрешением 2 выше и т. д.

Не уверен, что мое объяснение действительно ясно. Кроме того, я не знаю, обрабатывается ли этот вид графика с множественным разрешением какой-либо существующей программой печати. ​​

1 голос
/ 02 мая 2011

Интересно, можно ли выиграть, если ускорить поиск ваших очков? (Я был заинтригован деревьями R * (r star) некоторое время.)

Интересно, можно ли в этом случае использовать что-то вроде дерева r *. (при уменьшении более высокие узлы в дереве могут содержать информацию о более грубом, уменьшенном рендеринге, узлы дальше к листьям содержат отдельные выборки)

возможно, даже память отображает дерево (или какую-либо структуру, которую вы в конечном итоге используете) в память, чтобы поддерживать производительность и низкое использование ОЗУ. (вы переносите задачу управления памятью в ядро)

надеюсь, что это имеет смысл .. немного бродить. уже поздно!

...