【问题标题】:convert bitarray to set将位数组转换为设置
【发布时间】:2016-11-15 01:43:44
【问题描述】:

如何将位数组转换为使用 c++ 快速设置? 每个实际的位数组有 750,000 位。

示例 1:

bitarray: 01011111
set: {0,1,2,3,4,5,7}
or set: {1,3,4,5,6,7}

示例 2:

bitarray: 0101 1111 0001 0001
set: {0,4,8,9,10,11,12,14}
or set: {1,3,4,5,6,7,11,15}

该集合是一个无符号 32 位整数 (uint32_t) 数组。这两种设置都可以接受。

位数组在内存中是连续的。 bitarray 的第一位与 simd 正确对齐。现在我正在使用带有 std::vector 的自定义内存分配器来保存位数组。位数组中每 1 位在内存中 1 位。

谢谢。

更新:

this so question does the reverse

loop through bits in c

How to define and work with an array of bits in C?

gmpy 使用gmp library 的scan1 函数。 scan1 似乎找到第一组,如维基百科here

【问题讨论】:

  • 位数组的容器是什么?
  • 到目前为止它是一个 std::vector
  • std::vector?还是您将这些位存储在数字类型中?
  • 你卡在哪里了,你有什么尝试? 750,000 位只有大约 91.1 KB。预期的输出格式是什么?您是在要求括号中的逗号分隔的 ascii 值,如所示,还是其他?
  • 现在是数字类型。 8 位打包为无符号 8 位整数。

标签: c++ set bitarray


【解决方案1】:

如果我理解你的问题:

for (int i = 0; i < 750000; ++i) {
    if (bitarray_has(bitarray, i)) {
        set_of_numbers.push_back(i);
    }
}

我不相信走bitarray 会特别慢,但是如果你知道要创建多少个元素,push_back() 可以变得更快。然后你可以使用reserve()来预分配内存。

【讨论】:

  • 会尝试的。希望这足够快
  • 感谢有关保留的建议(我现在正在这样做......并且还使用原始指针)并回答。
  • bitarray_has 是什么?
  • 这是您编写的函数,用于确定整数是否由您的bitarray 表示。
【解决方案2】:

代码:

#include <iostream>
#include <vector>
#include <time.h>

using namespace std;

template <typename T>
uint32_t bitarray2set(T& v, uint32_t * ptr_set){
    uint32_t i;
    uint32_t base = 0;
    uint32_t * ptr_set_new = ptr_set;
    uint32_t size = v.capacity();
    for(i = 0; i < size; i++){
        find_set_bit(v[i], ptr_set_new, base);
        base += 8*sizeof(uint32_t);
    }
    return (ptr_set_new - ptr_set);
}

inline void find_set_bit(uint32_t n, uint32_t*& ptr_set, uint32_t base){
    // Find the set bits in a uint32_t
    int k = base;
    while(n){
        if (n & 1){
            *(ptr_set) = k;
            ptr_set++;
        }
        n = n >> 1;
        k++;
    }
}

template <typename T>
void rand_vector(T& v){
    srand(time(NULL));
    int i;
    int size = v.capacity();
    for (i=0;i<size;i++){
        v[i] = rand();
    }
}

template <typename T>
void print_vector(T& v, int size_in = 0){
    int i;

    int size;
    if (size_in == 0){
        size = v.capacity();
    } else {
        size = size_in;
    }
    for (i=0;i<size;i++){
        cout << v[i] << ' ';
    }
    cout << endl;
}

int main(void){
    const int test_size = 6000;
    vector<uint32_t> vec(test_size);
    vector<uint32_t> set(test_size*sizeof(uint32_t)*8);
    rand_vector(vec);
    //for (int i; i < 64; i++) vec[i] = -1;
    //cout << "input" << endl;
    print_vector(vec);
    //cout << "calculate result" << endl;

    int i;
    int rep = 10000;
    uint32_t res_size;

    struct timespec tp_start, tp_end;
    clock_gettime(CLOCK_MONOTONIC, &tp_start);
    for (i=0;i<rep;i++){
        res_size = bitarray2set(vec, set.data());
    }
    clock_gettime(CLOCK_MONOTONIC, &tp_end);
    double timing;
    const double nano = 0.000000001;

    timing = ((double)(tp_end.tv_sec  - tp_start.tv_sec )
           + (tp_end.tv_nsec - tp_start.tv_nsec) * nano) /(rep);

    cout << "timing per cycle: " << timing << endl;
    cout << "print result" << endl;
    //print_vector(set, res_size);
}

结果(用icc -O3 code.cpp -lrt编译)

...
timing per cycle: 0.000739613
print result

0.0008 秒将 768000 位转换为设置。但是每个周期至少有 10,000 个 768,000 位的数组。即每个周期 8 秒。这很慢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2010-10-15
    相关资源
    最近更新 更多