Самый быстрый способ очистить каждый k-й бит в boost:: dynamic_bitset

Каков самый быстрый способ очистить каждый бит kth в boost::dynamic_bitset, возможно, со смещения j?

В настоящее время я делаю это чертовски медленно (псевдокод):

for (i = j; i < bitset.size(); i += k) {
    bitset[i] = 0;
}

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


person orlp    schedule 13.04.2011    source источник
comment
Не могли бы вы исправить свой псевдокод, чтобы более точно описать ваше текущее решение? Этот код очищает бит ith много раз. Кроме того, почему вы увеличиваете на 2*k вместо k?   -  person Robᵩ    schedule 13.04.2011
comment
@Роб Адамс: Упс! Исправлено :) Эти 2*k и эти ошибки влезли из-за того, что я копировал/вставлял из файла, а потом быстро менял некоторые буквы для примера.   -  person orlp    schedule 13.04.2011


Ответы (2)


Для очень больших наборов битов вычислите маску длиной n бит (где n – исходный размер, например, 64 для x86_64), как предложил Ним, и примените ее.
Если исходная длина не кратна k, сдвиньте ее соответствующим образом.< br> Таким образом, если у вас исходная длина равна 10, и вы хотите установить только каждый третий бит 30-битного битового набора, вам потребуется 3 прохода следующим образом:
Первые 10 бит: 0010010010
Вторые 10 бит : 0100100100
Последние 10 бит: 1001001001
Таким образом, после применения каждой маски вам нужно сдвинуть ее (n%k) битов влево.

Повторяйте, пока не закончите.

person tstenner    schedule 13.04.2011
comment
If your native length is not a multiple of k, shift it accordingly. Я не понял эту часть. - person orlp; 13.04.2011
comment
Предположим, что собственная длина вашего процессора составляет 10 бит, и вы хотите сбросить каждый 3-й бит. Ваша маска — 0010010010. Для следующих 10 бит ваша маска должна быть 0100100100, ваша следующая маска — 1001001001 и т. д. В конце концов, у вас есть одна большая маска (0010010010|0100100100|100...), которую вы разделяете на свои собственные процессоры длина - person tstenner; 14.04.2011

хорошо, не уверен, что это быстрее, но я думаю, вы можете проверить:

Ключевой операцией является построение наборов битов маски, у вас должна быть таблица предварительно созданных масок (что позволит вам сбросить каждый k бит до каждого 32-го бита [на моей платформе unsigned long 32-битный]). Тогда дорогостоящей операцией является создание полной маски того же размера, что и входные данные — если она всегда одного размера, а память не является ограничением, вы также можете просто создать таблицу поиска для этого, а затем она просто &ing два наборы бит.

#include <iostream>
#include <limits>
#include <boost/dynamic_bitset.hpp>

using namespace std;

int main(void)
{
  boost::dynamic_bitset<> orig(64);
  for (int i = 0; i < orig.size(); ++i) {
    orig[i] = rand() % 2;
  }

  std::cout << orig << std::endl;

  unsigned long mask = 0x88888888; // reset every 4th bit
  boost::dynamic_bitset<> mbits(numeric_limits<unsigned long>::digits, mask);

  while(mbits.size() < orig.size())
    mbits.append(mask);
  mbits.resize(orig.size()); // incase not aligned
  mbits <<= 5; // arbitary starting point (i.e. j)
  std::cout << mbits << std::endl;

  mbits.flip();

  std::cout << mbits << std::endl;

  orig &= mbits;

  std::cout << orig << std::endl;

  return 0;
}

ОБНОВЛЕНИЕ. Хорошо, только что протестировал его очень грубо, и вы можете увидеть результат здесь: http://www.ideone.com/ez3Oc, с заранее созданной маской это может быть почти на 40% быстрее...

person Nim    schedule 13.04.2011
comment
Проблема в том, что я не буду использовать только 1 <= k <= 32, k может быть намного больше. - person orlp; 13.04.2011
comment
в таком случае, я думаю, то, что у вас есть, является наиболее оптимальным, если вам нужно динамически генерировать маску для каждого kго бита, вы можете также сразу установить бит в этом индексе в 0. Вышеупомянутое хорошо, если ваш k находится в этот диапазон. - person Nim; 13.04.2011