Мой процессор может выполнять арифметические операции только с 8-битными или 16-битными целыми числами без знака.
1) Это означает, что размер слова для этого процессора составляет 16 бит, верно?
Операции над словами - O (1).
Причина этого связана с фактической реализацией работы процессора на схемном уровне, верно?
Если бы я сложил два слова и получил бы число с более чем 16 битами, могу ли я указать следующее?
1) процессор может складывать числа, но сообщает только 16 младших значащих цифр.
2) чтобы также сообщать более 16 бит, процессор должен иметь программное обеспечение, которое разрешает эти операции с большими числами (числами, не умещающимися в слово).
В заключение,
Допустим, у меня есть слово w, представляющее собой 16-разрядную цифру, и мне нужны восемь младших цифр. Я умею ж & amp; 0xFF. Какова временная сложность этой операции? Это O (1) также из-за реализации процессора на схемном уровне?
4 ответа
Краткий ответ:
Да, одно побитовое И будет рассматриваться как O(1)
.
Подробнее:
Даже если вы посмотрели на количество операций с каждым битом, это все равно O(1)
. Фактическое количество битовых операций может зависеть от типа переменной, например 8 бит против 16 бит против 32 бит против 64 бит (даже 128 бит и более). Ключ не имеет значения, какой бы базовый компьютер ни использовал, он все равно будет выполнять constant
операций для его выполнения. Таким образом, даже если компьютеры развиваются с течением времени, побитовое И все равно будет O(1)
.
Еще один пример, который поможет добавить пояснения
Следующий блок кода - O (1):
print('Hello World');
print('Hello World');
print('Hello World');
Хотя мы печатаем hello world 3 раза, каждый раз, когда мы запускаем его, для его запуска и работы требуется постоянное количество времени, и это не займет больше времени, если кто-то загрузит в программу большой набор данных. Он просто напечатает 3 вещи, независимо от ввода.
В случае побитового И мы выполняем указанное количество подопераций, которые всегда имеют одно и то же число. например 8, 16, 32 и т.д. для одной операции, но всегда одинаковы или постоянны.
В вашем примере это звучит так, как будто вы пытаетесь показать, что у вас есть некоторые операции, которые также не требуют выполнения всех битов. Даже если эти более мелкие операции учитывают только 4 бита, скажем, 8. Ваш код всегда будет просто выполнять постоянное количество операций, когда попадет в этот код. Это все равно, что печатать 4 оператора hello world вместо 8 операторов hello world. В любом случае, 4 или 8 отпечатков, все равно постоянно.
Вот почему одна побитовая операция И - это O(1)
.
Для того, чтобы:
Нет. Если ваш процессор может выполнять 8- или 16-битные операции, это может быть 8- или 16-битный процессор. На самом деле, скорее всего, это будет 8 бит, поскольку большинство процессоров пытаются обрабатывать операции двойного размера.
Да, O (1). Но не потому, что это аппаратно, а потому, что аппаратно реализовано O (1). Также имейте в виду, что все O (x) на самом деле «умножены на константу». Таким образом, если что-то равно O (16), это действительно O (1), умноженное на константу 16.
Наконец, если у вас есть 16-битное слово и вам нужны младшие биты, и ваш процессор действительно поддерживает 8-битные операции, вы, вероятно, можете получить доступ к младшим битам с помощью инструкции MOV. Что-то вроде:
mov16 ax, (memory)
mov8 (othermemory), al
Если это недоступно, и вам нужно выполнить AND, тогда да, AND будет O (1), потому что это почти наверняка аппаратно. Даже если нет, в худшем случае это, вероятно, O (8), а это действительно псевдоним для O (1).
Вы, по-видимому, не совсем понимаете, что означает O (...).
нотация большого O требует переменной; например, при сортировке с использованием сравнения и замены известно, что массив из n элементов имеет размер не менее
O(n*log(n))
, и у вас есть n , который является переменной: как n увеличивает время сортировки, также увеличивается еще быстрее. Когда вы говорите, чтоx & 0xFF
равно O (1), о какой переменной вы говорите?big-O - это абстрактные алгоритмы, в которых n может расти до бесконечности. Если n и компьютер ограничены верхней границей, то любой алгоритм либо не завершается, либо ограничен константой (нет смысла обсуждать предел чего-либо как n увеличивается до бесконечности, если n не может превышать определенный предел).
Когда мы говорим о низкоуровневых аппаратных операциях, все операции - O (1). Некоторые из них быстрее и требуют всего одного «шага» (например, очистка регистра), некоторые требуют больше шагов (например, целочисленное деление). Однако даже деление займет не более n шагов, где n - небольшое целое число.
При обсуждении производительности различных алгоритмов в конкретном процессоре не имеет смысла использовать нотацию big-O, вы можете подсчитать количество машинных циклов, необходимых для завершения с явной формулой, возможно, в зависимости от размера ввода n , но где n не может расти до бесконечности.
Это то, что Кнут делает в TAOCP.
PS: к сожалению, современные процессоры настолько сложны, что подсчет циклов больше не работает в реальном мире. Они могут, например, разбивать инструкции на микрокоманды, перепланированные для параллельного выполнения, они поддерживают спекулятивное выполнение с отслеживанием с возвратом, предсказанием переходов и другими сложными для анализа методами. Вдобавок ко всему существует проблема кеширования, которая сегодня чрезвычайно важна, и разные, но совместимые модели могут иметь совершенно разные подходы. Единственный способ действительно узнать, сколько времени требуется для выполнения фрагмента кода с современными процессорами, - это просто запустить и измерить его по реальным данным на конкретной модели процессора и оборудовании.
Сначала о доп. Большинство процессоров имеют так называемый флаг переноса в регистре состояния процессора, который позволяет вам обнаруживать сложение и вычитание, выходящее за пределы разрядности регистра. Итак, узнайте размер регистров на вашем конкретном процессоре, чтобы определить пропускную способность шины данных, а затем узнайте, как вы можете проверить флаги регистра состояния. У большинства ЦП для этой цели есть SUB & ADD с переносом и без него.
Далее о временной сложности: вы не можете использовать для этого нотацию Big O. Вам нужно выяснить, сколько циклов требуется ЦП для выполнения операции в абсолютном времени (частота * циклы), тогда вам необходимо принять во внимание другие вещи, такие как доступ к памяти и доступ к кеш-памяти L1 и L2, чтобы выяснить общее время операции. возьму для этого CPU.
Наконец, доступ к памяти из ассемблерного кода (как вы, кажется, подразумеваете) позволяет работать намного эффективнее, чем с языками более высокого порядка, такими как Python. ЦП будет включать инструкции, которые могут регулировать адресацию своей памяти в соответствии с размером того, что вы ищете. C-подобные языки также будут иметь такую возможность в языке, но Python нет. В JavaScript даже нет целых чисел, но я отвлекся ...
Если ваша цель - понять низкоуровневое программирование, что всегда поможет вам лучше понять машину, особенно в отношении указателей и отладки, я бы посоветовал вам взять видео-класс по Arduino. Вы даже можете получить от этого удовольствие и начать новое хобби.
Похожие вопросы
Новые вопросы
algorithm
Алгоритм - это последовательность четко определенных шагов, которые определяют абстрактное решение проблемы. Используйте этот тег, если ваша проблема связана с дизайном алгоритма.