2011-01-07 9 views
0

Основываясь на ответах, которые у меня есть, я думаю, что эта проблема не имеет смысла. Спасибо за все ваши добрые ответы!, какой метод манипуляции бит эффективнее в C?

Я хочу получить двоичное число с его правыми j битами, установленными в 1, а другие установлены равными 0. в основном, есть два метода. Я хочу знать, какая из них более эффективна, или есть более эффективный способ, чем эти два?

1. ~(~0 << j) 
2. (1 << j) - 1 
+4

Вы проверили его? –

+1

как протестировать? положить их в петлю, а затем подсчитать часы? – Lion

+3

Если вы не можете проверить это разумно, то это, вероятно, не имеет значения.(Вы только оптимизируете, если это имеет значение, и если это не имеет значения, то чем вы оптимизируете в первую очередь?) – Mehrdad

ответ

3

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

Или, другими словами: не микро-оптимизируйте его, если это однострочное устройство является узким местом в вашем коде.

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

+0

спасибо! я не был уверен, имели ли эти два метода большие различия в производительности, потому что последний использует операцию «-», которая не является манипуляцией с битами. поэтому я задал этот вопрос здесь. – Lion

+0

Ха-ха, пожалуйста. :) Честно говоря, есть больше вещей, о которых нужно беспокоиться, когда вы кодируете; если вы только что начали программировать, легко попасть в ловушки, как это, особенно если вы начали с языка более низкого уровня. Не. Если вы ** действительно обеспокоены, тогда получите книгу, подобную [ths] (http://www.amazon.com/Computer-Organization-Design-Fourth-ebook/dp/B004HHOC7E) (написанный нашим профессором: ]) и начните читать вещи, такие как конвейерная обработка, местность памяти и т. д. Затем вы узнаете, как работает ЦП, и вы узнаете, когда такие вещи действительно меняют ситуацию, а когда нет. – Mehrdad

+0

Большое спасибо за ваш добрый ответ! – Lion

2

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

+0

Благодарим вас за ответ! :-) – Lion

0

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

+0

Благодарим вас за ответ! :-) – Lion

1

В дополнение к комментариям уже размещены:

В дополнение к бенчмаркинга, изучить ассемблер, который излучаемого. Оптимизатор мог бы создать тот же код для каждого ....

+0

, тогда мне нужно изучить некоторые простые инструкции на языке ассемблера, чтобы понять это. – Lion

+3

... нет, если они одинаковы! –

1

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

#include <ctime> 
main() 
{ 
    int i; 
    time_t start = time(); 
    for (i = 0; i < 1000000; i++) 
    { 
    // your operation here 
    } 
    time_t stop = time(); 
    double elapsed = difftime(stop, start); 
} 
+0

Спасибо за ваш код! :-) – Lion

+0

'time' обычно имеет только второе разрешение, поэтому вам нужно будет вложить 2 для циклов с 1000000 итерациями каждый, чтобы иметь любую надежду на измерение производительности. –

1

Если вы действительно хотите быстрый, использовать таблицу поиска:

const unsigned numbers[] = { 
     0x00000000, 
     0x00000001, 0x00000003, 0x00000007, 0x0000000f, 
     0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 
     0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 
     0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 
     0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 
     0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 
     0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 
     0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff}; 

unsigned h(unsigned j) { 
     return numbers[j]; 
} 

Расширение этого до 64 бит остается в качестве упражнения для читателя. И, как говорили другие, ничто из этого не имеет значения.

+0

спасибо за ваш код! :-) – Lion

+1

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

0

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

1

Если вы не изменили 0 на 0U, выражение ~(~0 << j) имеет поведение, специфичное для реализации, основанное на битовых шаблонах. С другой стороны, выражение (1 << j) - 1 является чисто арифметическим и не имеет в нем битовой арифметики, поэтому его значение хорошо определено во всех реализациях. Поэтому я всегда буду использовать последнее.