Мой процессор может выполнять арифметические операции только с 8-битными или 16-битными целыми числами без знака.

1) Это означает, что размер слова для этого процессора составляет 16 бит, верно?

Операции над словами - O (1).

Причина этого связана с фактической реализацией работы процессора на схемном уровне, верно?

Если бы я сложил два слова и получил бы число с более чем 16 битами, могу ли я указать следующее?

1) процессор может складывать числа, но сообщает только 16 младших значащих цифр.

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

В заключение,

Допустим, у меня есть слово w, представляющее собой 16-разрядную цифру, и мне нужны восемь младших цифр. Я умею ж & amp; 0xFF. Какова временная сложность этой операции? Это O (1) также из-за реализации процессора на схемном уровне?

5
evianpring 25 Апр 2016 в 04:24

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).

1
James Oravec 25 Апр 2016 в 15:07

Для того, чтобы:

  1. Нет. Если ваш процессор может выполнять 8- или 16-битные операции, это может быть 8- или 16-битный процессор. На самом деле, скорее всего, это будет 8 бит, поскольку большинство процессоров пытаются обрабатывать операции двойного размера.

  2. Да, 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).

2
aghast 25 Апр 2016 в 01:32

Вы, по-видимому, не совсем понимаете, что означает O (...).

  1. нотация большого O требует переменной; например, при сортировке с использованием сравнения и замены известно, что массив из n элементов имеет размер не менее O(n*log(n)), и у вас есть n , который является переменной: как n увеличивает время сортировки, также увеличивается еще быстрее. Когда вы говорите, что x & 0xFF равно O (1), о какой переменной вы говорите?

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

Когда мы говорим о низкоуровневых аппаратных операциях, все операции - O (1). Некоторые из них быстрее и требуют всего одного «шага» (например, очистка регистра), некоторые требуют больше шагов (например, целочисленное деление). Однако даже деление займет не более n шагов, где n - небольшое целое число.

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

Это то, что Кнут делает в TAOCP.

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

3
6502 26 Апр 2016 в 06:54

Сначала о доп. Большинство процессоров имеют так называемый флаг переноса в регистре состояния процессора, который позволяет вам обнаруживать сложение и вычитание, выходящее за пределы разрядности регистра. Итак, узнайте размер регистров на вашем конкретном процессоре, чтобы определить пропускную способность шины данных, а затем узнайте, как вы можете проверить флаги регистра состояния. У большинства ЦП для этой цели есть SUB & ADD с переносом и без него.

Далее о временной сложности: вы не можете использовать для этого нотацию Big O. Вам нужно выяснить, сколько циклов требуется ЦП для выполнения операции в абсолютном времени (частота * циклы), тогда вам необходимо принять во внимание другие вещи, такие как доступ к памяти и доступ к кеш-памяти L1 и L2, чтобы выяснить общее время операции. возьму для этого CPU.

Наконец, доступ к памяти из ассемблерного кода (как вы, кажется, подразумеваете) позволяет работать намного эффективнее, чем с языками более высокого порядка, такими как Python. ЦП будет включать инструкции, которые могут регулировать адресацию своей памяти в соответствии с размером того, что вы ищете. C-подобные языки также будут иметь такую возможность в языке, но Python нет. В JavaScript даже нет целых чисел, но я отвлекся ...

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

3
Laurent 25 Апр 2016 в 05:33