2013-11-19 6 views
29

Я использую панды для исследований в течение примерно двух месяцев. С большим количеством наборов данных событий среднего размера pandas + PyTables (интерфейс HDF5) делает огромную работу, позволяя мне обрабатывать гетерогенные данные, используя все инструменты Python, которые я знаю и люблю.Улучшить pandas (PyTables?) Производительность записи в формате HDF5

Вообще говоря, я использую фиксированный (ранее «Storer») формат в PyTables, так как мой рабочий процесс - это один раз, read-many и многие из моих наборов данных имеют такие размеры, что я могу загрузить 50-100 из них в память одновременно без каких-либо серьезных недостатков. (NB: Я много работаю над машинами класса Opteron с системной памятью 128 ГБ +.)

Однако для больших наборов данных (500 МБ и выше) я хотел бы иметь возможность использовать более масштабируемый случайный доступ и возможности запросов в формате «Таблицы» PyTables, чтобы я мог выполнять свои запросы из памяти, а затем загружать гораздо меньший результирующий набор в память для обработки. Однако здесь большое препятствие - это производительность записи. Да, как я уже сказал, мой рабочий процесс - однократный, чтение-много, но относительные времена все еще неприемлемы.

В качестве примера я недавно провел большую факторизацию Cholesky, которая заняла 3 минуты, 8 секунд (188 секунд) на моей 48-ядерной машине. Это создало файл трассировки ~ 2,2 ГБ - трасса генерируется параллельно с программой, поэтому нет дополнительного времени создания трассировки.

Первоначальное преобразование моего двоичного файла трассировки в формат pandas/PyTables занимает достойный кусок времени, но в основном потому, что двоичный формат намеренно не соответствует порядку, чтобы уменьшить влияние производительности самого генератора трассировки , Это также не имеет отношения к потерям производительности при переходе из формата Storer в формат таблицы.

Мои тесты изначально выполнялись с помощью pandas 0,12, numpy 1.7.1, PyTables 2.4.0 и numexpr 0.20.1. Моя 48-ядерная машина работает на частоте 2,8 ГГц на ядро, и я пишу файловую систему ext3, которая, вероятно, (но не обязательно) на SSD.

Я могу записать весь набор данных в файл формата HDF5 Storer (итоговый размер файла: 3,3 ГБ) за 7.1 секунды. Тот же набор данных, записанный в формат таблицы (итоговый размер файла также составляет 3,3 ГБ), занимает 178,7 секунды для записи.

Код выглядит следующим образом:

with Timer() as t: 
    store = pd.HDFStore('test_storer.h5', 'w') 
    store.put('events', events_dataset, table=False, append=False) 
print('Fixed format write took ' + str(t.interval)) 
with Timer() as t: 
    store = pd.HDFStore('test_table.h5', 'w') 
    store.put('events', events_dataset, table=True, append=False) 
print('Table format write took ' + str(t.interval)) 

и выход просто

Fixed format write took 7.1 
Table format write took 178.7 

Мой набор данных имеет 28,880,943 строки, а столбцы являются основными типами данных:

node_id   int64 
thread_id   int64 
handle_id   int64 
type    int64 
begin    int64 
end    int64 
duration   int64 
flags    int64 
unique_id   int64 
id    int64 
DSTL_LS_FULL float64 
L2_DMISS  float64 
L3_MISS   float64 
kernel_type  float64 
dtype: object 

. ..так, я не думаю, что должны быть какие-то специфические для конкретной информации проблемы с скоростью записи.

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

Теперь я понимаю, что в документации pandas говорится, что формат Storer обеспечивает значительно более быструю запись и немного быстрее читает. (У меня есть более быстрое чтение, так как чтение формата Storer, кажется, занимает около 2,5 секунд, в то время как чтение формата таблицы занимает около 10 секунд.) Но действительно кажется чрезмерным, что запись в формате таблицы должна занимать 25 раз, пока сохраняется формат Storer.

Может ли кто-либо из людей, вовлеченных в PyTables или pandas, объяснить архитектурные (или иные) причины, почему запись в запрашиваемый формат (который явно требует очень мало дополнительных данных), должен на порядок превышать? И есть ли надежда на улучшение этого в будущем? Мне бы хотелось перейти в один проект или другой, поскольку мое поле - высокопроизводительные вычисления, и я вижу значительный прецедент для обоих проектов в этом домене ... но было бы полезно получить некоторые разъяснения по связанные с этим вопросы, и/или некоторые советы о том, как ускорить работу тех, кто знает, как построена система.

EDIT:

Запуск прежних тестов с% prun в IPython дает следующее (несколько снижена для удобства чтения) вывода профиля для Сторера/Фиксированный формат:

%prun -l 20 profile.events.to_hdf('test.h5', 'events', table=False, append=False) 

3223 function calls (3222 primitive calls) in 7.385 seconds 

Ordered by: internal time 
List reduced from 208 to 20 due to restriction <20> 

ncalls tottime percall cumtime percall filename:lineno(function) 
    6 7.127 1.188 7.128 1.188 {method '_createArray' of 'tables.hdf5Extension.Array' objects} 
    1 0.242 0.242 0.242 0.242 {method '_closeFile' of 'tables.hdf5Extension.File' objects} 
    1 0.003 0.003 0.003 0.003 {method '_g_new' of 'tables.hdf5Extension.File' objects} 
    46 0.001 0.000 0.001 0.000 {method 'reduce' of 'numpy.ufunc' objects} 

и следующие за таблицах формат:

%prun -l 40 profile.events.to_hdf('test.h5', 'events', table=True, append=False, chunksize=1000000) 

    499082 function calls (499040 primitive calls) in 188.981 seconds 

    Ordered by: internal time 
    List reduced from 526 to 40 due to restriction <40> 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     29 92.018 3.173 92.018 3.173 {pandas.lib.create_hdf_rows_2d} 
     640 20.987 0.033 20.987 0.033 {method '_append' of 'tables.hdf5Extension.Array' objects} 
     29 19.256 0.664 19.256 0.664 {method '_append_records' of 'tables.tableExtension.Table' objects} 
     406 19.182 0.047 19.182 0.047 {method '_g_writeSlice' of 'tables.hdf5Extension.Array' objects} 
    14244 10.646 0.001 10.646 0.001 {method '_g_readSlice' of 'tables.hdf5Extension.Array' objects} 
     472 10.359 0.022 10.359 0.022 {method 'copy' of 'numpy.ndarray' objects} 
     80 3.409 0.043 3.409 0.043 {tables.indexesExtension.keysort} 
     2 3.023 1.512 3.023 1.512 common.py:134(_isnull_ndarraylike) 
     41 2.489 0.061 2.533 0.062 {method '_fillCol' of 'tables.tableExtension.Row' objects} 
     87 2.401 0.028 2.401 0.028 {method 'astype' of 'numpy.ndarray' objects} 
     30 1.880 0.063 1.880 0.063 {method '_g_flush' of 'tables.hdf5Extension.Leaf' objects} 
     282 0.824 0.003 0.824 0.003 {method 'reduce' of 'numpy.ufunc' objects} 
     41 0.537 0.013 0.668 0.016 index.py:607(final_idx32) 
    14490 0.385 0.000 0.712 0.000 array.py:342(_interpret_indexing) 
     39 0.279 0.007 19.635 0.503 index.py:1219(reorder_slice) 
     2 0.256 0.128 10.063 5.031 index.py:1099(get_neworder) 
     1 0.090 0.090 119.392 119.392 pytables.py:3016(write_data) 
    57842 0.087 0.000 0.087 0.000 {numpy.core.multiarray.empty} 
    28570 0.062 0.000 0.107 0.000 utils.py:42(is_idx) 
    14164 0.062 0.000 7.181 0.001 array.py:711(_readSlice) 

EDIT 2:

Запуск снова с предварительной версией pandas 0.13 (вытащил 20 ноября 2013 года примерно в 11:00 по восточному стандартному времени), время записи для формата таблиц значительно улучшилось, но до сих пор не сравнивается «разумно» со скоростями записи Storer/Fixed формат.

%prun -l 40 profile.events.to_hdf('test.h5', 'events', table=True, append=False, chunksize=1000000) 

     499748 function calls (499720 primitive calls) in 117.187 seconds 

    Ordered by: internal time 
    List reduced from 539 to 20 due to restriction <20> 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     640 22.010 0.034 22.010 0.034 {method '_append' of 'tables.hdf5Extension.Array' objects} 
     29 20.782 0.717 20.782 0.717 {method '_append_records' of 'tables.tableExtension.Table' objects} 
     406 19.248 0.047 19.248 0.047 {method '_g_writeSlice' of 'tables.hdf5Extension.Array' objects} 
    14244 10.685 0.001 10.685 0.001 {method '_g_readSlice' of 'tables.hdf5Extension.Array' objects} 
     472 10.439 0.022 10.439 0.022 {method 'copy' of 'numpy.ndarray' objects} 
     30 7.356 0.245 7.356 0.245 {method '_g_flush' of 'tables.hdf5Extension.Leaf' objects} 
     29 7.161 0.247 37.609 1.297 pytables.py:3498(write_data_chunk) 
     2 3.888 1.944 3.888 1.944 common.py:197(_isnull_ndarraylike) 
     80 3.581 0.045 3.581 0.045 {tables.indexesExtension.keysort} 
     41 3.248 0.079 3.294 0.080 {method '_fillCol' of 'tables.tableExtension.Row' objects} 
     34 2.744 0.081 2.744 0.081 {method 'ravel' of 'numpy.ndarray' objects} 
     115 2.591 0.023 2.591 0.023 {method 'astype' of 'numpy.ndarray' objects} 
     270 0.875 0.003 0.875 0.003 {method 'reduce' of 'numpy.ufunc' objects} 
     41 0.560 0.014 0.732 0.018 index.py:607(final_idx32) 
    14490 0.387 0.000 0.712 0.000 array.py:342(_interpret_indexing) 
     39 0.303 0.008 19.617 0.503 index.py:1219(reorder_slice) 
     2 0.288 0.144 10.299 5.149 index.py:1099(get_neworder) 
    57871 0.087 0.000 0.087 0.000 {numpy.core.multiarray.empty} 
     1 0.084 0.084 45.266 45.266 pytables.py:3424(write_data) 
     1 0.080 0.080 55.542 55.542 pytables.py:3385(write) 

я заметил во время выполнения этих тестов, Есть длительные периоды, когда письма, кажется, «пауза» (файл на диске не активно растет), и тем не менее есть и низкая загрузка процессора во время некоторых из этих периодов.

Я начинаю подозревать, что некоторые известные ограничения ext3 могут плохо взаимодействовать с pandas или PyTables. Ext3 и другие файловые системы, не основанные на экстентах, иногда пытаются быстро развязать большие файлы, и подобная производительность системы (низкое использование ЦП, но длительное время ожидания) очевидна даже во время простого «rm» 1GB-файла, например.

Чтобы уточнить, в каждом тестовом случае я должен был удалить существующий файл, если он есть, перед началом теста, чтобы не повлечь за собой удаление или переполнение файла ext3.

Однако при повторном запуске этого теста с индексом = Нет производительность резко улучшается (~ 50 с против 120 при индексировании). Таким образом, казалось бы, либо этот процесс по-прежнему будет привязан к процессору (у моей системы есть относительно старые процессоры AMD Opteron Istanbul, работающие на частоте 2.8ГГц, хотя у нее также есть 8 сокетов с 6 ядрами в каждом, все, кроме одного, из конечно, сидеть без дела во время записи) или что существует некоторый конфликт между попытками PyTables или pandas манипулировать/читать/анализировать файл, когда он частично или полностью работает с файловой системой, что приводит к патологически плохому поведению ввода-вывода, когда индексирование происходит.

EDIT 3:

@ предложенные тесты Джеффа на меньшем наборе данных (1,3 ГБ на диске), после обновления PyTables от 2,4 до 3.0.0, получил меня здесь:

In [7]: %timeit f(df) 
1 loops, best of 3: 3.7 s per loop 

In [8]: %timeit f2(df) # where chunksize= 2 000 000 
1 loops, best of 3: 13.8 s per loop 

In [9]: %timeit f3(df) # where chunksize= 2 000 000 
1 loops, best of 3: 43.4 s per loop 

В самом деле , моя производительность, кажется, превзошла его во всех сценариях, за исключением того, когда включена индексация (по умолчанию). Тем не менее, индексирование по-прежнему кажется убийцей, и если способ интерпретации вывода из top и ls, поскольку я запускаю эти тесты правильно, остаются периоды времени, когда не происходит ни существенной обработки, ни записи файла (т. Е. , Использование процессора для процесса Python около 0, а размер файла остается постоянным).Я могу только предположить, что это чтение файлов. Почему чтение файлов вызывает замедление, мне трудно понять, так как я могу надежно загрузить весь 3+ GB файл с этого диска в память менее чем за 3 секунды. Если они не читаются в файлах, то какая система «ждет»? (Никто не регистрируется в машине, и нет другой активности файловой системы.)

На данный момент, с обновленными версиями соответствующих модулей python, производительность для моего первоначального набора данных сводится к следующим рисункам. Особый интерес представляют системное время, которое, как я полагаю, является, по крайней мере, верхней границей времени, затрачиваемого на выполнение IO, и времени на стене, что, по-видимому, объясняет эти загадочные периоды отсутствия активности записи/отсутствия ЦП.

In [28]: %time f(profile.events) 
CPU times: user 0 ns, sys: 7.16 s, total: 7.16 s 
Wall time: 7.51 s 

In [29]: %time f2(profile.events) 
CPU times: user 18.7 s, sys: 14 s, total: 32.7 s 
Wall time: 47.2 s 

In [31]: %time f3(profile.events) 
CPU times: user 1min 18s, sys: 14.4 s, total: 1min 32s 
Wall time: 2min 5s 

Тем не менее, похоже, что индексация вызывает значительное замедление для моего варианта использования. Возможно, мне следует попытаться ограничить индексированные поля вместо простого выполнения случая по умолчанию (что вполне может быть индексирование по всем полям в DataFrame)? Я не уверен, как это повлияет на время запроса, особенно в тех случаях, когда запрос выбирается на основе неиндексированного поля.

По запросу Джера, ptdump полученного файла.

ptdump -av test.h5 
/(RootGroup) '' 
    /._v_attrs (AttributeSet), 4 attributes: 
    [CLASS := 'GROUP', 
    PYTABLES_FORMAT_VERSION := '2.1', 
    TITLE := '', 
    VERSION := '1.0'] 
/df (Group) '' 
    /df._v_attrs (AttributeSet), 14 attributes: 
    [CLASS := 'GROUP', 
    TITLE := '', 
    VERSION := '1.0', 
    data_columns := [], 
    encoding := None, 
    index_cols := [(0, 'index')], 
    info := {1: {'type': 'Index', 'names': [None]}, 'index': {}}, 
    levels := 1, 
    nan_rep := 'nan', 
    non_index_axes := 
    [(1, ['node_id', 'thread_id', 'handle_id', 'type', 'begin', 'end', 'duration', 'flags', 'unique_id', 'id', 'DSTL_LS_FULL', 'L2_DMISS', 'L3_MISS', 'kernel_type'])], 
    pandas_type := 'frame_table', 
    pandas_version := '0.10.1', 
    table_type := 'appendable_frame', 
    values_cols := ['values_block_0', 'values_block_1']] 
/df/table (Table(28880943,)) '' 
    description := { 
    "index": Int64Col(shape=(), dflt=0, pos=0), 
    "values_block_0": Int64Col(shape=(10,), dflt=0, pos=1), 
    "values_block_1": Float64Col(shape=(4,), dflt=0.0, pos=2)} 
    byteorder := 'little' 
    chunkshape := (4369,) 
    autoindex := True 
    colindexes := { 
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False} 
    /df/table._v_attrs (AttributeSet), 15 attributes: 
    [CLASS := 'TABLE', 
    FIELD_0_FILL := 0, 
    FIELD_0_NAME := 'index', 
    FIELD_1_FILL := 0, 
    FIELD_1_NAME := 'values_block_0', 
    FIELD_2_FILL := 0.0, 
    FIELD_2_NAME := 'values_block_1', 
    NROWS := 28880943, 
    TITLE := '', 
    VERSION := '2.7', 
    index_kind := 'integer', 
    values_block_0_dtype := 'int64', 
    values_block_0_kind := ['node_id', 'thread_id', 'handle_id', 'type', 'begin', 'end', 'duration', 'flags', 'unique_id', 'id'], 
    values_block_1_dtype := 'float64', 
    values_block_1_kind := ['DSTL_LS_FULL', 'L2_DMISS', 'L3_MISS', 'kernel_type']] 

и еще% prun с обновленными модулями и полным набором данных:

%prun -l 25 %time f3(profile.events) 
CPU times: user 1min 14s, sys: 16.2 s, total: 1min 30s 
Wall time: 1min 48s 

     542678 function calls (542650 primitive calls) in 108.678 seconds 

    Ordered by: internal time 
    List reduced from 629 to 25 due to restriction <25> 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     640 23.633 0.037 23.633 0.037 {method '_append' of 'tables.hdf5extension.Array' objects} 
     15 20.852 1.390 20.852 1.390 {method '_append_records' of 'tables.tableextension.Table' objects} 
     406 19.584 0.048 19.584 0.048 {method '_g_write_slice' of 'tables.hdf5extension.Array' objects} 
    14244 10.591 0.001 10.591 0.001 {method '_g_read_slice' of 'tables.hdf5extension.Array' objects} 
     458 9.693 0.021 9.693 0.021 {method 'copy' of 'numpy.ndarray' objects} 
     15 6.350 0.423 30.989 2.066 pytables.py:3498(write_data_chunk) 
     80 3.496 0.044 3.496 0.044 {tables.indexesextension.keysort} 
     41 3.335 0.081 3.376 0.082 {method '_fill_col' of 'tables.tableextension.Row' objects} 
     20 2.551 0.128 2.551 0.128 {method 'ravel' of 'numpy.ndarray' objects} 
     101 2.449 0.024 2.449 0.024 {method 'astype' of 'numpy.ndarray' objects} 
     16 1.789 0.112 1.789 0.112 {method '_g_flush' of 'tables.hdf5extension.Leaf' objects} 
     2 1.728 0.864 1.728 0.864 common.py:197(_isnull_ndarraylike) 
     41 0.586 0.014 0.842 0.021 index.py:637(final_idx32) 
    14490 0.292 0.000 0.616 0.000 array.py:368(_interpret_indexing) 
     2 0.283 0.142 10.267 5.134 index.py:1158(get_neworder) 
     274 0.251 0.001 0.251 0.001 {method 'reduce' of 'numpy.ufunc' objects} 
     39 0.174 0.004 19.373 0.497 index.py:1280(reorder_slice) 
    57857 0.085 0.000 0.085 0.000 {numpy.core.multiarray.empty} 
     1 0.083 0.083 35.657 35.657 pytables.py:3424(write_data) 
     1 0.065 0.065 45.338 45.338 pytables.py:3385(write) 
    14164 0.065 0.000 7.831 0.001 array.py:615(__getitem__) 
    28570 0.062 0.000 0.108 0.000 utils.py:47(is_idx) 
     47 0.055 0.001 0.055 0.001 {numpy.core.multiarray.arange} 
    28570 0.050 0.000 0.090 0.000 leaf.py:397(_process_range) 
    87797 0.048 0.000 0.048 0.000 {isinstance} 
+0

может быть так. Я видел так много ответов на панды, что я решил, что стоит посмотреть, будет ли кто-нибудь прыгать с «у этого есть очевидный ответ, и это XYZ!» Но я скоро перейду через него. –

ответ

5

Это интересная дискуссия. Я думаю, что Питер получает потрясающую производительность для фиксированного формата, потому что формат записывается одним выстрелом, а также что у него действительно хороший SSD (он может писать более 450 МБ/с).

Приложение к таблице является более сложной операцией (набор данных должен быть увеличен, а новые записи должны быть проверены, чтобы мы могли следить за тем, чтобы они соответствовали схеме таблицы). Вот почему добавление строк в таблицы, как правило, медленнее (но все же, Джефф получает ~ 70 МБ/с, что довольно хорошо). То, что Джефф получает больше скорости, чем Питер, вероятно, связано с тем, что у него лучший процессор.

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

8

Вот подобное сравнение я только что сделал. Его около 1/3 из данных 10M строк. Окончательный размер является Abou 1.3GB

я определить 3 временных функций:

Test Фиксированный формат (так называемый Шторер в 0.12). Это записывается в формате массива PyTables

def f(df): 
    store = pd.HDFStore('test.h5','w') 
    store['df'] = df 
    store.close() 

Запись в формате таблицы с использованием формата таблицы PyTables. Не создавайте индекс.

def f2(df): 
    store = pd.HDFStore('test.h5','w') 
    store.append('df',df,index=False) 
    store.close() 

То же, f2, но создать индекс (который обычно делается)

def f3(df): 
    store = pd.HDFStore('test.h5','w') 
    store.append('df',df) 
    store.close() 

Создать рамку

In [25]: df = concat([DataFrame(np.random.randn(10000000,10)),DataFrame(np.random.randint(0,10,size=50000000).reshape(10000000,5))],axis=1) 

In [26]: df 
Out[26]: 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 10000000 entries, 0 to 9999999 
Columns: 15 entries, 0 to 4 
dtypes: float64(10), int64(5) 


v0.12.0 

In [27]: %timeit f(df) 
1 loops, best of 3: 14.7 s per loop 

In [28]: %timeit f2(df) 
1 loops, best of 3: 32 s per loop 

In [29]: %timeit f3(df) 
1 loops, best of 3: 40.1 s per loop 

master/v0.13.0 

In [5]: %timeit f(df) 
1 loops, best of 3: 12.9 s per loop 

In [6]: %timeit f2(df) 
1 loops, best of 3: 17.5 s per loop 

In [7]: %timeit f3(df) 
1 loops, best of 3: 24.3 s per loop 

Timing пробегов с тем же файлом, как это предусмотрено ОП (ссылка ниже)

In [4]: df = pd.read_hdf('test.h5','df') 

In [5]: df 
Out[5]: 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 28880943 entries, 0 to 28880942 
Columns: 14 entries, node_id to kernel_type 
dtypes: float64(4), int64(10) 

Как f1, фиксированный формат

In [6]: %timeit df.to_hdf('test.hdf','df',mode='w') 
1 loops, best of 3: 36.2 s per loop 

Как f2, формат таблицы, ни индекс

In [7]: %timeit df.to_hdf('test.hdf','df',mode='w',format='table',index=False) 
1 loops, best of 3: 45 s per loop 

In [8]: %timeit df.to_hdf('test.hdf','df',mode='w',format='table',index=False,chunksize=2000000) 
1 loops, best of 3: 44.5 s per loop 

Как f3, Формат таблицы с индексом

In [9]: %timeit df.to_hdf('test.hdf','df',mode='w',format='table',chunksize=2000000) 
1 loops, best of 3: 1min 36s per loop 

Как f3, формат таблицы с индексом, с прессованным блоком

Показать оригинальный файл (test.h5, и сжатый, test.hdf)

In [13]: !ls -ltr test.h* 
-rw-r--r-- 1 jreback users 3471518282 Nov 20 18:20 test.h5 
-rw-rw-r-- 1 jreback users 649327780 Nov 20 21:17 test.hdf 

Несколько замечаний.

  • Не создавая индекс, вы можете сделать нетривиальную разницу во времени. Я также считаю, что если у вас есть индекс на основе строк, это может существенно ухудшить время записи. Тем не менее, вы всегда хотите создать индекс, чтобы сделать поиск очень быстрым.

    Вы не указали, что такое ваш индекс, и его сортировка (хотя я думаю только, что это делает небольшую разницу).

  • штраф за нарушение в моих примерах примерно равен 2x (хотя я видел, что он несколько больше, когда ВКЛЮЧАЕТ время индекса). Таким образом, ваш 7s (1/2 моего времени), для 3x число, которое я пишу, довольно подозрительно. Я использую достаточно быстрый дисковый массив. Однако, если вы используете диск с флэш-памятью, это возможно.

  • master/v0.13.0 (релиз очень скоро), существенно улучшает время записи на таблицах.

  • вы можете попробовать установить параметр chunksize на большее число при записи данных (по умолчанию 100000). Цель «относительно» низкого числа - иметь постоянное использование памяти. (например, если это больше, вы будете использовать больше памяти, теоретически он должен писать быстрее).

  • Таблицы предлагают 2 преимущества по сравнению с фиксированным форматом: 1) поиск запроса и 2) пригодность. Чтение всей таблицы также не дает преимуществ, поэтому, если вы ТОЛЬКО хотите прочитать всю таблицу, рекомендуется использовать фиксированный формат. (В моем опыте гибкость таблиц значительно перевешивает штраф записи, но YMMV)

Нижняя линия повторить тайминги (используйте IPython, как он будет работать несколько тестов). Если вы можете воспроизвести свои результаты, тогда pls опубликует% prun, и я посмотрю.

Update:

поэтому рекомендуемый способ для таблицы такого размера, чтобы сжать с blosc и использовать мастер панд/0.13.0 вместе с PyTables 3.0.0

+0

Спасибо за ответ! Я знаю о преимуществах Tables vs Fixed/Storer, и те, которые вы указали, являются, конечно, основными причинами, которые я заинтересован в том, чтобы это работало лучше. К сожалению, производительность с вашим тестовым кодом неплохо отражает мои предыдущие результаты. 3.53s за цикл с f(), 51s за цикл с f2() и 1min 14s за цикл с f3(). Честно говоря, я не знаю, что такое резервное хранилище на этой машине (это не мое администрирование), но мне кажется, что если f() еще быстрее на моей машине, чем ваша, другие не должны отстают от ваших результатов так значительно ... –

+0

если вы могли бы попробовать с мастером и опубликовать прут для формата таблицы, будет gr8 – Jeff

+0

результаты не очень вдохновляют. это определенно лучше, но где-то все еще наблюдается значительное замедление. на данный момент кажется, что, возможно, эти результаты несколько зависят от дизайна/типа файловой системы. Разумеется, ext3 является настолько распространенным, насколько это возможно, похоже, что это может заслуживать дальнейшего рассмотрения. –

Смежные вопросы