Какова стандартная структура данных OCaml с самой быстрой итерацией? - PullRequest
10 голосов
/ 05 января 2010

Я ищу контейнер, который обеспечивает самые быстрые неупорядоченные итерации через инкапсулированные элементы. Другими словами, «добавь один раз, повторяй много раз».

Есть ли среди стандартных модулей OCaml достаточно быстрый (такой, что дальнейшая его оптимизация будет бесполезной)? Или какие-нибудь сторонние GPL-готовые?

AFAIK, есть только один компилятор OCaml, поэтому концепция быстрой работы более или менее ясна ...

... Но после того, как я увидел пару ответов, похоже, это не так. Конечно, существует множество структур данных, которые допускают итерацию O (n) через контейнер размера n. Но задача, которую я решаю, одна из тех, где разница между O (n) и O (2n) имеет значение; -).

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

В C я бы сразу выбрал простой массив. Вопрос в том, что мне выбрать в OCaml?

Ответы [ 5 ]

10 голосов
/ 05 января 2010

Вы вряд ли добьетесь большего успеха, чем встроенные массивы и списки, поскольку они написаны вручную в C, если вы не привязаны к собственной собственной реализации итератора. Массив будет вести себя почти так же, как массив в C (непрерывно выделенный блок памяти, содержащий последовательность значений элементов), возможно, с некоторыми дополнительными косвенными указателями из-за упаковки. Список реализован в точности так, как вы ожидаете: в виде ячеек со значением и указателем «следующий». Массивы предоставят вам лучшее расположение для распакованных типов (особенно float s, которые имеют сверхспециальную распакованную реализацию).

Для получения информации о реализации массивов и списков см. Раздел 18.3 руководства OCaml и файлы byterun/mlvalues.h, byterun/array.c и byterun/alloc.c в исходном коде OCaml.

От опрашивающего : действительно, Array оказался самым быстрым решением. Однако он только превзошел List на 7%. Может быть, это потому, что тип элемента массива не был достаточно простым: это был алгебраический тип. Hashtbl показал результат в 4 раза хуже, чем ожидалось.

Итак, я выберу Array, и я принимаю это. хорошо.

8 голосов
/ 06 января 2010

Чтобы знать наверняка, вам нужно измерить . Основываясь на машинных инструкциях, которые может сгенерировать компилятор, я бы попробовал массив, затем список.

  • Для доступа к элементу массива требуется проверка границ, адресная арифметика и загрузка

  • Доступ к заголовку списка требует загрузки, проверки пустого списка и загрузки с известным смещением времени компиляции.

Сведения о том, что быстрее, вероятно, зависят от вашего приложения и того, что еще происходит на вашем компьютере. Они также зависят от типа элементов; например, если они являются числами с плавающей точкой, ocamlopt может быть достаточно умным, чтобы создать распакованный массив, который сохранит вам уровень косвенности.

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

Наконец, обратите внимание, что может быть только один компилятор OCaml, но он имеет два внутренних конца: байт-код и собственный код. Естественно, если вы заботитесь об этом уровне производительности, вы используете версию с нативным кодом ocamlopt. Правильно?

Пожалуйста, проведите измерения и отредактируйте результаты в своем вопросе.

6 голосов
/ 06 января 2010

Не забудьте о Bigarray с, они наиболее близки к массивам C (просто кусок памяти), но не могут содержать произвольные значения OCaml. Также рассмотрите возможность отключения проверки границ (unsafe_set / get). И, конечно, вы должны сначала профиль.

3 голосов
/ 05 января 2010

Массив - линейный фрагмент памяти с элементами, которые посещаются в последовательном порядке - лучше всего использует кэш данных L1 ЦП.

1 голос
/ 05 января 2010

Все общие структуры данных являются итеративными за время O (n), поэтому различия между структурами данных будут только постоянными (и, весьма вероятно, незначительными).

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

...