Я только что доказал, что сито Эратосфена менее эффективно, чем пробное деление?

Я пытался сравнить скорость выполнения двух алгоритмов: программы C грубой силы для печати простых чисел (10 000 чисел) и программы Sieve of Eratosthenes C (также 10 000 простых чисел).

Мое измеренное время выполнения алгоритма сита было: 0,744 секунды.

Мое измеренное время выполнения алгоритма грубой силы составило: 0,262 секунды.

Однако мне сказали, что алгоритм «Решето Эратосфена» более эффективен, чем метод грубой силы, и поэтому я подумал, что он будет работать быстрее. Так что либо я ошибаюсь, либо моя программа ошибочна (в чем я сомневаюсь).

Поэтому мой вопрос: Поскольку я получил результаты, противоположные тем, которые я ожидал, доказывает ли это, что Сито Эратосфена действительно является менее эффективным алгоритмом с точки зрения скорости по сравнению с испытанием? деление?

Я не уверен, имеет ли это какое-то значение, но я использую компилятор Dev C ++ и Windows 7.


person C_Intermediate_Learner    schedule 16.08.2013    source источник
comment
Короткий ответ: не обязательно. Эффективность определяется асимптотически (для сколь угодно большого ввода). Многие очень эффективные алгоритмы получают свою эффективность от той или иной формы кэширования / предварительного выделения ... что делает их медленнее, чем грубая сила для крошечных входных данных. Однако в вашем случае я нахожу ОЧЕНЬ удивительным, что грубая сила работает лучше, чем сито эратосфенов (которое, по сути, является «умной» грубой силой). Вы на 100% уверены в его реализации?   -  person val    schedule 16.08.2013
comment
Это зависит от того, как реализованы алгоритмы. Я решил эту проблему в проекте Эйлера с использованием сита из эратосфенов, и это намного быстрее.   -  person D.Pham    schedule 16.08.2013
comment
Большинство тестов производительности в Windows очень неточны и часто неверны. Каждый раз, обсуждая измерение времени выполнения в Windows, вы должны упомянуть, как вы измеряли время. Кроме того, поскольку Windows 7 не является ОСРВ, вы не можете просто измерить время один раз, вам придется сделать это несколько раз и вычислить среднее или среднее время. Вы также должны протестировать два алгоритма одновременно. Если вы измеряете алгоритм A 100 раз, а затем предположите, что какой-то процесс запускается в фоновом режиме, когда вы собираетесь измерить алгоритм B. Тогда вы, очевидно, получите неверные результаты.   -  person Lundin    schedule 16.08.2013
comment
А теперь пришло время Сито Аткина   -  person P0W    schedule 16.08.2013
comment
Правильный способ задать этот вопрос - это опубликовать код, который использовался для реализации обоих этих алгоритмов, и рассчитать время. Тогда нам не пришлось бы просто размышлять о том, что может быть причиной поведения, которое вы наблюдаете при определенных обстоятельствах. Мы могли бы на самом деле сказать вам, что не так с вашим кодом. Вопрос был отложен, потому что он неполный. Вы можете отредактировать его, включив в него свой код и более подробное описание проблемы, чтобы повторно открыть его.   -  person Cody Gray    schedule 16.08.2013
comment
Так что либо я ошибаюсь, либо моя программа ошибочна (в чем я сомневаюсь). - Я не могу представить, почему вы в этом сомневаетесь ... Скорее всего, ваша программа даже не реализует Сито Эратосфена; это распространенная ошибка даже опытных программистов: cs.hmc.edu/ ~ oneill / paper / Sieve-JFP.pdf   -  person Jim Balter    schedule 16.08.2013
comment
как это происходит сейчас все чаще и чаще, указанная причина закрытия - [самоцензура]. Вполне разумно дать ответ на этот вопрос в нескольких абзацах. Вот схема: измерить эмпирические порядки роста для обоих алгоритмов. Одного балла недостаточно; трех пунктов много. Вот и все, и этого нет среди приведенных здесь ответов.   -  person Will Ness    schedule 17.08.2013
comment
Мета-обсуждение этого вопроса   -  person Gilles 'SO- stop being evil'    schedule 18.08.2013
comment
@CodyGray, мы все еще можем обсудить, означает ли что-нибудь одно измерение размером, или нужно проводить сравнение для большего количества входных данных? Даже если мы ничего не знаем о рассматриваемом коде, на этот вопрос есть ответ. :) Я отредактировал, чтобы конкретизировать вопрос.   -  person Will Ness    schedule 19.08.2013
comment
@Will Конечно, вы заметите, что я не был одним из тех, кто голосовал за закрытие. Я разместил этот комментарий в качестве конструктивного совета для того, кто задает вопрос, после прочтения мета-вопроса, на который уже ссылался Жиль. Будучи постоянным участником Meta, я мог видеть надпись на стене: этот вопрос вот-вот будет закрыт, и опыт подсказал мне, что проблема, скорее всего, связана с отсутствием кода. Многие люди думают, что рекомендации в FAQ более конкретны: для хороших вопросов SO нужен код.   -  person Cody Gray    schedule 20.08.2013
comment
Для протокола, я удалил лишнее форматирование, которое оставляло у меня неприятный привкус во рту, когда я смотрел этот вопрос, и проголосовал за его повторное открытие. Я все еще думаю, что было бы лучше, если бы код, используемый для проверки проблемы, был также опубликован, но это не значит, что я считаю вопрос неприемлемым в его текущем состоянии.   -  person Cody Gray    schedule 20.08.2013
comment
@CodyGray: Хорошая попытка исправить это, но я все же думаю, что код, используемый для алгоритмов, должен быть включен. В вопросе говорится, доказывает ли это, что Сито Эратосфена действительно является менее эффективным алгоритмом, поскольку все, что мы знаем, причина более медленного времени может быть связана исключительно с плохой реализацией. Я думаю, что единственный возможный ответ, который можно было бы дать, - это алгоритм Решета Эратосфена с вашими конкретными реализациями, безусловно, медленнее ... но это все равно что спрашивать, что быстрее, 2 секунды или 7 секунд? ... бессмысленно   -  person musefan    schedule 20.08.2013
comment
новому близкому избирателю: почему бы вам не опубликовать комментарий, объясняющий, что здесь все еще неясно? (Я не могу представить, что это может быть, объясните, пожалуйста). Возможно, этот вопрос можно прояснить, не прибегая к закрытию и повторному открытию.   -  person Will Ness    schedule 21.08.2013
comment
Код все еще отсутствует через день. Без кода это совершенно бесполезно, и его следует закрыть и удалить.   -  person starblue    schedule 22.08.2013
comment
@starblue Я, очевидно, категорически не согласен, как видно из моего ответа. По этому поводу предстоит содержательное обсуждение и содержательный ответ. Который, надеюсь, дал. Стоит - важно - знать, что каким бы ни был код, его эффективность лучше всего оценивать с помощью техники эмпирических порядков роста и измерения сравнительной скорости только для одной точки размера ввода. бессмысленно.   -  person Will Ness    schedule 22.08.2013


Ответы (6)


TL; DR: бессмысленно сравнивать скорость вариантов кода при одном размере ввода; сравнение эмпирических порядков роста действительно отражает алгоритмическую природу кода и будет согласованным на разных тестовых платформах для одного и того же тестового диапазона входных размеров. Сравнение абсолютных значений скорости имеет смысл только для вариантов кода, которые демонстрируют такое же асимптотическое или, по крайней мере, локальное поведение роста.


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

Таким образом, даже если на некотором вводе code_1 работает в 10 раз быстрее, чем code_2, но его время выполнения удваивается с каждым удвоением размера ввода, тогда как для code_2 оно увеличивается только как 1.1x, очень скоро code_2 станет намного быстрее, чем code_1.

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

В частности, теоретическая сложность пробного деления составляет O(n^1.5 / (log n)^0.5) в n простых числах, обычно рассматриваемых как ~ n^1.40..1.45 эмпирический порядок роста (но изначально он может быть ~n^1.3 для меньших размеров входных данных). Для сита Эратосфена это O(n log n log (log n)), обычно обозначаемый ~ n^1.1..1.2. Но, безусловно, существуют неоптимальные реализации как пробного деления, так и сита Эратосфена, которые работают на ~n^2.0 и хуже.

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

Прогноз с известной достоверностью - это то, что научный метод это все о.


Кстати, у вас очень долгое время работы. Вычисление 10 000 простых чисел должно происходить почти мгновенно, намного меньше, чем 1/100 секунды для программы C, выполняемой на быстром блоке. Возможно, вы также измеряете время печати. Не надо. :)

person Will Ness    schedule 21.08.2013

Нет, затраченное время выполнения не является стандартом для измерения эффективности, поскольку оно варьируется от платформы к платформе - утверждение «мой алгоритм работал за 10 секунд» практически не дает информации о самом алгоритме. В дополнение к этому вам нужно будет перечислить все спецификации среды и другие процессы, запущенные одновременно, и это будет огромным беспорядком. Отсюда и развитие порядковых обозначений (Big Oh, Little Oh, Omega и т. Д.).

Эффективность обычно подразделяется на два подраздела:

  1. Эффективность времени.
  2. Эффективность использования пространства.

... где один алгоритм может быть чрезвычайно эффективным по времени, но очень неэффективным с точки зрения пространства. Применяется наоборот. Алгоритмы анализируются на основе их асимптотического поведения при масштабировании количества инструкций, которые им необходимо выполнить для заданного входа n. Это объяснение очень высокого уровня в области, которая тщательно изучается PhD компьютерными учеными - я предлагаю вам прочитать об этом больше здесь, чтобы найти лучшее низкоуровневое объяснение.

Обратите внимание: я прикрепляю ссылку для обозначения Big Oh - все родственные обозначения можно найти на этой странице Википедии, и обычно это хорошее место для начала. Это также затронет разницу в пространственной и временной эффективности.

Небольшое применение эффективности времени с помощью Big Oh:

Рассмотрим следующую рекурсивную функцию в Racket (была бы в Python, если бы я знал это - лучший псевдокод, который я могу сделать):

(define (fn_a input_a)
  (cond
    [(empty? input_a) empty]
    [(empty? (rest input_a)) input_a]
    [(> (first input_a) (fn_a (rest input_a))) (cons (first input_a) empty)]
    [else (fn_a (rest input_a))]))

... мы видим, что: empty?, rest, > и first - все O (1). Мы также замечаем, что в худшем случае выполняется вызов fn_a в третьем условии и четвертом условии для rest из input_a. Тогда мы можем записать наше рекуррентное соотношение как T (n) = O (1) + 2T (n - 1). Глядя на это на диаграмме рекуррентных отношений, мы видим, что fn_a имеет порядок O (2 ^ n), потому что в худшем случае выполняются два рекурсивных вызова.

Также важно отметить, что по формальному определению Big Oh также правильно (хотя и бесполезно) утверждать, что fn_a равно O (3 ^ n). Многие алгоритмы при анализе указываются с использованием Big Oh, однако было бы более целесообразно использовать Big Theta для ужесточения границ, что по сути означает: самый низкий, наиболее точный порядок по отношению к данному алгоритму.

Будьте осторожны, прочтите официальные определения!

person Jacob Pollack    schedule 16.08.2013
comment
Время выполнения что-то значит для моих пользователей. Конечно, big-O имеет постоянные коэффициенты, поэтому этот способ анализа эффективности может не быть прямо пропорционален времени выполнения. - person doctorlove; 16.08.2013
comment
@doctorlove, улучшил формулировку, которую я использовал. Это должно быть передано лучше сейчас (в соответствии с моим первоначальным намерением). - person Jacob Pollack; 16.08.2013
comment
Лучше :-) Я все еще подозреваю, что если OP запускал два алгоритма на одном компьютере, время могло указывать на ошибку кода, но для этого потребуется более одного эксперимента - person doctorlove; 16.08.2013
comment
Я полностью согласен с Джейкобом, хотя время выполнения (и обратите внимание, что это также не то же самое, что время настенных часов в системах, где вы можете быть вытеснены), важно, и постоянные коэффициенты должны быть уменьшены - обозначение сложности бесконечно важнее, когда масштабирование N, которое во многих случаях является чистой прибылью - person Leeor; 16.08.2013
comment
или вы можете просто измерить его эмпирически, чтобы получить полную картину. - person Will Ness; 19.08.2013

Означает ли более длительное время выполнения менее эффективный алгоритм?

Не обязательно. Эффективность программы измеряется не только затраченным временем, но и затрачиваемыми ресурсами. Пространство - еще один фактор, о котором следует помнить при рассмотрении эффективности.

Из wiki: -

Для максимальной эффективности мы хотим минимизировать использование ресурсов. Однако различные ресурсы (например, время, пространство) нельзя сравнивать напрямую, поэтому какой из двух алгоритмов считается более эффективным, часто зависит от того, какой показатель эффективности считается наиболее важным, например требуется высокая скорость, минимальное использование памяти или какая-то другая мера?

person Rahul Tripathi    schedule 16.08.2013

В целом: да, но когда вы опускаетесь на диапазон менее 1 секунды, появляется много шума, который может сбивать с толку ...

Выполняет каждый тест много раз и использует некоторую статистику по результатам (например, среднее значение или среднее значение / отклонение в зависимости от того, насколько вы заботитесь)

И / или заставить его выполнять больше работы - например, находить большее количество простых чисел.

person John3136    schedule 16.08.2013

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

Будьте осторожны при измерениях - убедитесь, что ваши инструменты для измерения времени точны.

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

person doctorlove    schedule 16.08.2013

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

В качестве альтернативы в одной из ваших реализаций может быть большой

Наконец, эффективность алгоритмов можно измерить по необходимому объему памяти (но эта мера менее распространена, особенно с учетом того, что память в настоящее время настолько дешевая).

person laurie    schedule 16.08.2013