微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

正在检查大型订购清单中的成员资格?

如何解决正在检查大型订购清单中的成员资格?

我在C中有一段代码可以顺序生成许多数字,我想检查这些数字是否在排序列表中。该列表是使用numpy创建的,并且具有〜10 9 个元素,如上所述,这些元素的排列顺序为从最小到最大。 C代码检查其结果是否在此列表中的最快最快方法是什么?我应该使用哪种数据结构(如果包含C ++ STL)?我当时以为在无序地图上进行二进制搜索可能最快,但是我不确定。

此外(这可能是最重要的事情),我该如何在程序中包括数字列表-只需将其复制并粘贴到文件中即可?还是冒险进入sqlite或其他数据库

解决方法

理论上最快的方法(实际上也可能是实践中的方法)是O(1):使用位图,即std::vector<bool>(具有特殊的实现,每个条目仅使用一位)。仅当且仅当位i在原始列表中时,才将其设置为true。这使您可以通过单个内存提取来执行检查。缺点是,这可能会花费比您更多的内存,具体取决于列表中的最大数量。

如果不合适,可以考虑std::set(O(n log n)),std::unordered_set(O(1))或经过排序的std::vector进行二进制搜索( O(n log n))。测量一下哪个最快。

如果仍然不够出色,您还可以考虑使用Bloom filter作为快速检查来排除许多未命中的对象,然后再开始进行较慢的搜索。

,

您的数组已排序。只需将 C 标准库bsearch函数与 array 结合使用。如果您是用Numpy制作的,则将它们作为 binary 按顺序(即

)写到 file
import numpy as np

array = np.arange(1,3000000,3,dtype='int32')
array.tofile('array.bin')

,如果在Unix / Linux中,则使用mmap将其映射到内存中,只读:

#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>

int cmpfunc(const void *a,const void *b)
{
   const int32_t *A = a,*B = b;
   return (*A > *B) - (*A < *B);
}

bool is_in_array(int32_t *base,size_t length,int32_t element) {
    return bsearch(&element,base,length,sizeof (int32_t),cmpfunc);
}

int main(void) {
    int fd = open("array.bin",O_RDONLY);
    struct stat statbuf;

    fstat(fd,&statbuf);
    size_t length = statbuf.st_size;
    void *base = mmap(NULL,PROT_READ,MAP_SHARED,fd,0);

    size_t elements = length / sizeof(int32_t);

    for (int32_t i = 0; i < 3 * elements; i += 10000) {
        printf("%" PRId32 " is %sin the set\n",i,is_in_array(base,elements,i) ? "" : "not ");
    }

    munmap(base,length);
    close(fd);
}

bsearch不一定绝对最快,但是也不错。如果速度太慢,则可以考虑内联算法。


如果数字范围确实小到0到1.3G,则可以将其组织为位图。但是,如果您的数字是int64或md5哈希值,则位图将不起作用。

对于位图,您可以使用

import numpy as np

array = np.arange(1,dtype='int32')
bytearray = np.zeros(array.max() + 1,dtype='bool')
bytearray[array] = 1
bitarray = np.packbits(bytearray)
bitarray.tofile('bitarray.bin')

和:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>

int main(void) {
    struct stat statbuf;
    int fd = open("bitarray.bin",O_RDONLY);

    fstat(fd,&statbuf);
    size_t length = statbuf.st_size;
    unsigned char *base = mmap(NULL,0);

    size_t limit = length * CHAR_BIT;

    for (size_t i = 0; i < limit + 30000; i += 10000) {
        bool is_in = false;
        if (i < limit) {
            size_t index = i / CHAR_BIT;
            int bit = i % CHAR_BIT;
            is_in = (base[index] & (1 << bit));
        }

        printf("%" PRIu32 " is %sin the set\n",is_in ? "" : "not ");
    }

    munmap(base,length);
    close(fd);
}

当然,最简单的就是在Python中做这两种事情-Numpy的二进制搜索形式为searchsorted

,

在C代码中,我将使用一个无符号整数的简单数组,并让每个位代表一个数字。这将需要大约。 200MB的内存。如果您的系统具有8G,并且这是唯一正在运行的程序,那么我认为200MB的价格对于快速查找是合理的。

查找功能可以简单地是:

bool check(uint32_t value,uint32_t* arr)
{
    uint32_t tmp = arr[value >> 5];
    return tmp & (1 << (value & 0x1F));
}

您刚放置在启动时读取的txt文件中的Numpy数据。

对于Numpy中的每个值,请调用以下函数:

void set(uint32_t value,uint32_t* arr)
{
    uint32_t idx = value >> 5;
    arr[idx] = arr[idx] | (1  << (value & 0x1F));
}

在插入任何Numpy值之前,请使用calloc动态分配数组。喜欢:

uint32_t numpyVal;
uint32_t* arr = calloc(MAX_NUM/32,sizeof *arr);
while(getNextNumpyValue(&numpyVal) 
{
   set(numpyVal,arr);
}

if (check(SOME_VALUE,arr)
{
    printf("Found\n");
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。