(Dis)доказательство того, что один алгоритм работает быстрее, чем другой из-за внутренних языков

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

нам было поручено реализовать, среди прочего, алгоритм Union-Find и его оптимизации (объединение по глубине, размеру). Случайно (делая что-то, что я считал необходимым для правильности алгоритма) я обнаружил другой способ оптимизации алгоритма.

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

проект был на java, и структуры данных, которые я использовал, были основаны на простых массивах целых чисел (объект, а не int) Позже, при оценке проекта, мне сказали, что это, вероятно, связано с "кэшированием Java", но я ничего не могу найти в интернете о том, как кэширование повлияет на это.

каков был бы лучший способ, без вычисления сложности алгоритма, доказать или опровергнуть, что моя оптимизация так быстро из-за способа java делать вещи? Внедрение его в другом (более низком уровне? язык? Но кто сказал, что язык не одно и то же?

спасибо

4 ответов


единственный способ-доказать наихудшую (средний случай и т. д.) сложность алгоритма.

потому что, если вы этого не сделаете, это может быть просто следствием комбинации

  • конкретных данных
  • размер данных
  • некоторые аспекты оборудования
  • некоторые аспекты реализации языка
  • etc.

обычно очень сложно выполнить такую задачу, учитывая современные VM! Как вы намекаете, они выполняют все виды вещей за вашей спиной. Вызовы методов становятся встроенными, объекты используются повторно. Так далее. Ярким примером является то,как тривиальные циклы компилируются, если они явно не выполняют ничего, кроме подсчета. Или как funtioncall в функциональном программировании встроены или оптимизированы tail-call.

Далее, у вас есть трудность доказать свою точку зрения в целом на любой набор данных. O(n^2) может быть намного быстрее, чем, казалось бы, более быстрый, скажем, o (n), алгоритм. Два примера

  1. сортировка пузырьков быстрее при сортировке почти отсортированного сбора данных, чем быстрая сортировка.
  2. быстрая сортировка в общем случае, конечно, быстрее.

обычно обозначение big-O намеренно игнорирует константы, которые в практической ситуации могут означать жизнь или смерть для вашей реализации. и эти константы, возможно, и поразили вас. Так что ... практика 0.00001 * n ^2 (скажем, время работы вашего алгоритма) быстрее, чем 1000000 * N log n

поэтому рассуждение трудно, учитывая ограниченную информацию, которую вы предоставляете.


вероятно, что компилятор или JVM нашли оптимизацию для вашего кода. Вы можете попробовать прочитать байт-код, который выводится javac компилятор и отключение компиляции JIT во время выполнения с помощью .


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