C(和 C++)中的便攜式 Roaring 點圖,完全支援您最喜歡的編譯器(GNU GCC、LLVM 的 clang、Visual Studio、Apple Xcode、Intel oneAPI)。包含在開源 C 軟體 Awesome C 清單中。
位元集,也稱為點陣圖,通常用作快速資料結構。不幸的是,它們可能使用太多記憶體。為了彌補這一點,我們經常使用壓縮位圖。
Roaring 位圖是壓縮位圖,其效能往往優於常規壓縮位圖,例如 WAH、EWAH 或 Concise。它們被多個主要係統(例如Apache Lucene)和衍生系統(例如Solr 和Elasticsearch、Metamarkets 的Druid、LinkedIn Pinot、Netflix Atlas、Apache Spark、OpenSearchServer、Cloud Torrent、Whoosh、InfluxDB、Pilosa、Bleve、Microsoft Visual Studio Team )使用服務 (VSTS) 和 eBay 的 Apache Kylin。 CRoaring 函式庫用於多個系統,例如 Apache Doris、ClickHouse、Redpanda 和 StarRocks。 YouTube SQL 引擎 Google Procella 使用 Roaring 點陣圖進行索引。
我們發表了一篇關於該庫的設計和評估的同行評審文章:
人們發現咆哮位圖在許多重要的應用程式中都能很好地工作:
盡可能使用 Roaring 進行點陣圖壓縮。不要使用其他點陣圖壓縮方法(Wang et al., SIGMOD 2017)
有一個用於實現之間互通性的序列化格式規範。因此,可以從 C++ 序列化 Roaring Bitmap,在 Java 中讀取它,修改它,將其序列化回來,然後在 Go 和 Python 中讀取它。
CRoring 的主要目標是提供充分利用最新硬體的高效能低階實現。 Roaring 點圖已經可以透過 Java、Go、Rust... 實現在各種平台上使用。 CRoring 是一個旨在透過接近最新硬體來實現卓越效能的函式庫。
(c) 2016-...CRoring 作者。
幾乎沒有人能夠存取實際的大端系統。儘管如此,我們透過模擬器支援大端系統,例如 IBM s390x,但 IO 序列化除外,它僅在小端系統上支援(請參閱問題 423)。
CRoring 庫可以合併到單一來源檔案中,從而更容易整合到其他專案中。此外,透過將所有關鍵程式碼編譯到一個編譯單元中,可以提高效能。有關基本原理,請參閱 SQLite 文件或相應的 Wikipedia 條目。選擇此路線的使用者不需要依賴 CRoaring 的建置系統(基於 CMake)。
我們提供合併文件作為每個版本的一部分。
如果 Linux 或 macOS 使用者安裝了最新的 C 或 C++ 編譯器以及標準實用程式 ( wget
),則可以按照以下說明進行操作。
wget https://github.com/RoaringBitmap/CRoaring/releases/download/v2.1.0/roaring.c
wget https://github.com/RoaringBitmap/CRoaring/releases/download/v2.1.0/roaring.h
wget https://github.com/RoaringBitmap/CRoaring/releases/download/v2.1.0/roaring.hh
demo.c
的新文件,其中包含以下內容: #include <stdio.h>
#include <stdlib.h>
#include "roaring.c"
int main () {
roaring_bitmap_t * r1 = roaring_bitmap_create ();
for ( uint32_t i = 100 ; i < 1000 ; i ++ ) roaring_bitmap_add ( r1 , i );
printf ( "cardinality = %dn" , ( int ) roaring_bitmap_get_cardinality ( r1 ));
roaring_bitmap_free ( r1 );
bitset_t * b = bitset_create ();
for ( int k = 0 ; k < 1000 ; ++ k ) {
bitset_set ( b , 3 * k );
}
printf ( "%zu n" , bitset_count ( b ));
bitset_free ( b );
return EXIT_SUCCESS ;
}
demo.cpp
的新文件,其中包含以下內容: # include < iostream >
# include " roaring.hh " // the amalgamated roaring.hh includes roaring64map.hh
# include " roaring.c "
int main () {
roaring::Roaring r1;
for ( uint32_t i = 100 ; i < 1000 ; i++) {
r1. add (i);
}
std::cout << " cardinality = " << r1. cardinality () << std::endl;
roaring::Roaring64Map r2;
for ( uint64_t i = 18000000000000000100ull ; i < 18000000000000001000ull ; i++) {
r2. add (i);
}
std::cout << " cardinality = " << r2. cardinality () << std::endl;
return 0 ;
}
cc -o demo demo.c
c++ -std=c++11 -o demopp demo.cpp
./demo
cardinality = 900
1000
./demopp
cardinality = 900
cardinality = 900
如果您喜歡 CMake 和 CPM,則只需在CMakeLists.txt
檔案中新增幾行即可取得CRoaring
版本。請參閱我們的 CPM 演示以了解更多詳細資訊。
cmake_minimum_required ( VERSION 3.10)
project (roaring_demo
LANGUAGES CXX C
)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_C_STANDARD 11)
add_executable (hello hello.cpp)
# You can add CPM.cmake like so:
# mkdir -p cmake
# wget -O cmake/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
include (cmake/CPM.cmake)
CPMAddPackage(
NAME roaring
GITHUB_REPOSITORY "RoaringBitmap/CRoaring"
GIT_TAG v2.0.4
OPTIONS "BUILD_TESTING OFF"
)
target_link_libraries (hello roaring::roaring)
如果您喜歡 CMake,則只需在CMakeLists.txt
檔案中新增幾行即可取得CRoaring
版本。請參閱我們的演示以了解更多詳細資訊。
如果您在本機上安裝了 CRoaring 函式庫,則可以將其與 CMake 的find_package
函數一起使用,如下例所示:
cmake_minimum_required ( VERSION 3.15)
project (test_roaring_install VERSION 0.1.0 LANGUAGES CXX C)
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD_REQUIRED ON )
set (CMAKE_C_STANDARD 11)
set (CMAKE_C_STANDARD_REQUIRED ON )
find_package (roaring REQUIRED)
file (WRITE main.cpp "
#include <iostream>
#include " roaring/roaring.hh "
int main() {
roaring::Roaring r1;
for (uint32_t i = 100; i < 1000; i++) {
r1.add(i);
}
std::cout << " cardinality = " << r1.cardinality() << std::endl;
return 0;
}" )
add_executable (repro main.cpp)
target_link_libraries (repro PUBLIC roaring::roaring)
要自行產生合併文件,您可以呼叫 bash 腳本...
./amalgamation.sh
如果您喜歡靜默輸出,可以使用以下指令重新導向stdout
:
./amalgamation.sh > /dev/null
(Bash shell 在 Linux 和 macOS 下是標準的。Bash shell 在 Windows 下作為 GitHub Desktop 的一部分以Git Shell
名稱提供。因此,如果您已從 GitHub Desktop 中克隆了CRoaring
GitHub 存儲庫,則可以右鍵單擊CRoaring
,選擇Git Shell
,然後輸入上述指令 )
無需呼叫 CRoaring 目錄中的腳本。您可以從要寫入合併文件的任何目錄中呼叫它。
它將為 C 使用者產生三個檔案: roaring.h
、 roaring.c
和amalgamation_demo.c
...以及一些簡短的說明。 amalgamation_demo.c
檔案是一個簡短的範例,而roaring.h
和roaring.c
是「合併」檔案(包括專案的所有來源檔案和頭檔)。這意味著您只需將檔案roaring.h
和roaring.c
複製到您的專案中即可開始!無需生成庫!請參閱amalgamation_demo.c
檔。
C介面在檔案中找到
我們還有一個 C++ 介面:
一些用戶必須處理大量數據。對於這些使用者來說,了解addMany
(C++) roaring_bitmap_or_many
(C) 函數可能很重要,因為在可能的情況下批量添加值會更快、更經濟。此外,定期呼叫runOptimize
(C++) 或roaring_bitmap_run_optimize
(C) 函數可能會有所幫助。
我們有根據 Google 基準建立的微基準。在 Linux 或 macOS 下,您可以按如下方式運行它們:
cmake -B build -D ENABLE_ROARING_MICROBENCHMARKS=ON
cmake --build build
./build/microbenchmarks/bench
預設情況下,基準測試工具選擇一個資料集(例如CRoaring/benchmarks/realdata/census1881
)。我們有幾個資料集,您可以選擇其他資料集:
./build/microbenchmarks/bench benchmarks/realdata/wikileaks-noquotes
您可以出於基準測試的目的停用某些功能。例如,假設您有一個 x64 處理器,即使您的處理器和編譯器都支援 AVX-512,您也可以在沒有 AVX-512 的情況下對程式碼進行基準測試:
cmake -B buildnoavx512 -D ROARING_DISABLE_AVX512=ON -D ENABLE_ROARING_MICROBENCHMARKS=ON
cmake --build buildnoavx512
./buildnoavx512/microbenchmarks/bench
您也可以在沒有 AVX 或 AVX-512 的情況下進行基準測試:
cmake -B buildnoavx -D ROARING_DISABLE_AVX=ON -D ENABLE_ROARING_MICROBENCHMARKS=ON
cmake --build buildnoavx
./buildnoavx/microbenchmarks/bench
對於一般用戶,CRoring 將套用預設分配器,無需額外代碼。但是,也為那些想要自訂記憶體分配器的人提供了全域記憶體掛鉤。這是一個例子:
#include <roaring.h>
int main (){
// define with your own memory hook
roaring_memory_t my_hook { my_malloc , my_free ...};
// initialize global memory hook
roaring_init_memory_hook ( my_hook );
// write you code here
...
}
預設我們使用:
static roaring_memory_t global_memory_hook = {
. malloc = malloc ,
. realloc = realloc ,
. calloc = calloc ,
. free = free ,
. aligned_malloc = roaring_bitmap_aligned_malloc ,
. aligned_free = roaring_bitmap_aligned_free ,
};
我們要求free
/ aligned_free
函數遵循 C 約定,其中free(NULL)
/ aligned_free(NULL)
不起作用。
此範例假設 CRoaring 已建置並且您正在連結相應的庫。預設情況下,CRoaring 會將其頭檔安裝在roaring
目錄中。如果您使用合併腳本,且未連結預先建置的 CRoaring 庫,則可以新增行#include "roaring.c"
並將#include <roaring/roaring.h>
替換為#include "roaring.h"
。
#include <roaring/roaring.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
bool roaring_iterator_sumall ( uint32_t value , void * param ) {
* ( uint32_t * ) param += value ;
return true; // iterate till the end
}
int main () {
// create a new empty bitmap
roaring_bitmap_t * r1 = roaring_bitmap_create ();
// then we can add values
for ( uint32_t i = 100 ; i < 1000 ; i ++ ) roaring_bitmap_add ( r1 , i );
// check whether a value is contained
assert ( roaring_bitmap_contains ( r1 , 500 ));
// compute how many bits there are:
uint32_t cardinality = roaring_bitmap_get_cardinality ( r1 );
printf ( "Cardinality = %d n" , cardinality );
// if your bitmaps have long runs, you can compress them by calling
// run_optimize
uint32_t expectedsizebasic = roaring_bitmap_portable_size_in_bytes ( r1 );
roaring_bitmap_run_optimize ( r1 );
uint32_t expectedsizerun = roaring_bitmap_portable_size_in_bytes ( r1 );
printf ( "size before run optimize %d bytes, and after %d bytesn" ,
expectedsizebasic , expectedsizerun );
// create a new bitmap containing the values {1,2,3,5,6}
roaring_bitmap_t * r2 = roaring_bitmap_from ( 1 , 2 , 3 , 5 , 6 );
roaring_bitmap_printf ( r2 ); // print it
// we can also create a bitmap from a pointer to 32-bit integers
uint32_t somevalues [] = { 2 , 3 , 4 };
roaring_bitmap_t * r3 = roaring_bitmap_of_ptr ( 3 , somevalues );
// we can also go in reverse and go from arrays to bitmaps
uint64_t card1 = roaring_bitmap_get_cardinality ( r1 );
uint32_t * arr1 = ( uint32_t * ) malloc ( card1 * sizeof ( uint32_t ));
assert ( arr1 != NULL );
roaring_bitmap_to_uint32_array ( r1 , arr1 );
roaring_bitmap_t * r1f = roaring_bitmap_of_ptr ( card1 , arr1 );
free ( arr1 );
assert ( roaring_bitmap_equals ( r1 , r1f )); // what we recover is equal
roaring_bitmap_free ( r1f );
// we can go from arrays to bitmaps from "offset" by "limit"
size_t offset = 100 ;
size_t limit = 1000 ;
uint32_t * arr3 = ( uint32_t * ) malloc ( limit * sizeof ( uint32_t ));
assert ( arr3 != NULL );
roaring_bitmap_range_uint32_array ( r1 , offset , limit , arr3 );
free ( arr3 );
// we can copy and compare bitmaps
roaring_bitmap_t * z = roaring_bitmap_copy ( r3 );
assert ( roaring_bitmap_equals ( r3 , z )); // what we recover is equal
roaring_bitmap_free ( z );
// we can compute union two-by-two
roaring_bitmap_t * r1_2_3 = roaring_bitmap_or ( r1 , r2 );
roaring_bitmap_or_inplace ( r1_2_3 , r3 );
// we can compute a big union
const roaring_bitmap_t * allmybitmaps [] = { r1 , r2 , r3 };
roaring_bitmap_t * bigunion = roaring_bitmap_or_many ( 3 , allmybitmaps );
assert (
roaring_bitmap_equals ( r1_2_3 , bigunion )); // what we recover is equal
// can also do the big union with a heap
roaring_bitmap_t * bigunionheap =
roaring_bitmap_or_many_heap ( 3 , allmybitmaps );
assert ( roaring_bitmap_equals ( r1_2_3 , bigunionheap ));
roaring_bitmap_free ( r1_2_3 );
roaring_bitmap_free ( bigunion );
roaring_bitmap_free ( bigunionheap );
// we can compute intersection two-by-two
roaring_bitmap_t * i1_2 = roaring_bitmap_and ( r1 , r2 );
roaring_bitmap_free ( i1_2 );
// we can write a bitmap to a pointer and recover it later
uint32_t expectedsize = roaring_bitmap_portable_size_in_bytes ( r1 );
char * serializedbytes = malloc ( expectedsize );
// When serializing data to a file, we recommend that you also use
// checksums so that, at deserialization, you can be confident
// that you are recovering the correct data.
roaring_bitmap_portable_serialize ( r1 , serializedbytes );
// Note: it is expected that the input follows the specification
// https://github.com/RoaringBitmap/RoaringFormatSpec
// otherwise the result may be unusable.
// The 'roaring_bitmap_portable_deserialize_safe' function will not read
// beyond expectedsize bytes.
// We also recommend that you use checksums to check that serialized data corresponds
// to the serialized bitmap. The CRoaring library does not provide checksumming.
roaring_bitmap_t * t = roaring_bitmap_portable_deserialize_safe ( serializedbytes , expectedsize );
if ( t == NULL ) { return EXIT_FAILURE ; }
const char * reason = NULL ;
// If your input came from an untrusted source, then you need to validate the
// resulting bitmap. Failing to do so could lead to undefined behavior, crashes and so forth.
if (! roaring_bitmap_internal_validate ( t , & reason )) {
return EXIT_FAILURE ;
}
// At this point, the bitmap is safe.
assert ( roaring_bitmap_equals ( r1 , t )); // what we recover is equal
roaring_bitmap_free ( t );
// we can also check whether there is a bitmap at a memory location without
// reading it
size_t sizeofbitmap =
roaring_bitmap_portable_deserialize_size ( serializedbytes , expectedsize );
assert ( sizeofbitmap ==
expectedsize ); // sizeofbitmap would be zero if no bitmap were found
// We can also read the bitmap "safely" by specifying a byte size limit.
// The 'roaring_bitmap_portable_deserialize_safe' function will not read
// beyond expectedsize bytes.
// We also recommend that you use checksums to check that serialized data corresponds
// to the serialized bitmap. The CRoaring library does not provide checksumming.
t = roaring_bitmap_portable_deserialize_safe ( serializedbytes , expectedsize );
if ( t == NULL ) {
printf ( "Problem during deserialization.n" );
// We could clear any memory and close any file here.
return EXIT_FAILURE ;
}
// We can validate the bitmap we recovered to make sure it is proper.
// If the data came from an untrusted source, you should call
// roaring_bitmap_internal_validate.
const char * reason_failure = NULL ;
if (! roaring_bitmap_internal_validate ( t , & reason_failure )) {
printf ( "safely deserialized invalid bitmap: %sn" , reason_failure );
// We could clear any memory and close any file here.
return EXIT_FAILURE ;
}
assert ( roaring_bitmap_equals ( r1 , t )); // what we recover is equal
roaring_bitmap_free ( t );
free ( serializedbytes );
// we can iterate over all values using custom functions
uint32_t counter = 0 ;
roaring_iterate ( r1 , roaring_iterator_sumall , & counter );
// we can also create iterator structs
counter = 0 ;
roaring_uint32_iterator_t * i = roaring_iterator_create ( r1 );
while ( i -> has_value ) {
counter ++ ; // could use i->current_value
roaring_uint32_iterator_advance ( i );
}
// you can skip over values and move the iterator with
// roaring_uint32_iterator_move_equalorlarger(i,someintvalue)
roaring_uint32_iterator_free ( i );
// roaring_bitmap_get_cardinality(r1) == counter
// for greater speed, you can iterate over the data in bulk
i = roaring_iterator_create ( r1 );
uint32_t buffer [ 256 ];
while ( 1 ) {
uint32_t ret = roaring_uint32_iterator_read ( i , buffer , 256 );
for ( uint32_t j = 0 ; j < ret ; j ++ ) {
counter += buffer [ j ];
}
if ( ret < 256 ) {
break ;
}
}
roaring_uint32_iterator_free ( i );
roaring_bitmap_free ( r1 );
roaring_bitmap_free ( r2 );
roaring_bitmap_free ( r3 );
return EXIT_SUCCESS ;
}
我們也支援 C 語言中的高效 64 位元壓縮位圖:
roaring64_bitmap_t *r2 = roaring64_bitmap_create();
for ( uint64_t i = 100 ; i < 1000 ; i++) roaring64_bitmap_add(r2, i);
printf ( " cardinality (64-bit) = %d n " , ( int ) roaring64_bitmap_get_cardinality(r2));
roaring64_bitmap_free (r2);
該 API 類似於傳統的 32 位元位圖。請參閱頭檔roaring64.h
(與roaring.h
進行比較)。
我們支援約定位集(未壓縮)作為庫的一部分。
簡單的例子:
bitset_t * b = bitset_create ();
bitset_set ( b , 10 );
bitset_get ( b , 10 ); // returns true
bitset_free ( b ); // frees memory
更進階的例子:
bitset_t * b = bitset_create ();
for ( int k = 0 ; k < 1000 ; ++ k ) {
bitset_set ( b , 3 * k );
}
// We have bitset_count(b) == 1000.
// We have bitset_get(b, 3) is true
// You can iterate through the values:
size_t k = 0 ;
for ( size_t i = 0 ; bitset_next_set_bit ( b , & i ); i ++ ) {
// You will have i == k
k += 3 ;
}
// We support a wide range of operations on two bitsets such as
// bitset_inplace_symmetric_difference(b1,b2);
// bitset_inplace_symmetric_difference(b1,b2);
// bitset_inplace_difference(b1,b2);// should make no difference
// bitset_inplace_union(b1,b2);
// bitset_inplace_intersection(b1,b2);
// bitsets_disjoint
// bitsets_intersect
在某些情況下,您可能會想要將 Roaring 位圖轉換為傳統(未壓縮)點陣圖。事實上,位元集具有一些優點,例如在某些情況下具有更高的查詢效能。以下程式碼說明如何執行此操作:
roaring_bitmap_t * r1 = roaring_bitmap_create ();
for ( uint32_t i = 100 ; i < 100000 ; i += 1 + ( i % 5 )) {
roaring_bitmap_add ( r1 , i );
}
for ( uint32_t i = 100000 ; i < 500000 ; i += 100 ) {
roaring_bitmap_add ( r1 , i );
}
roaring_bitmap_add_range ( r1 , 500000 , 600000 );
bitset_t * bitset = bitset_create ();
bool success = roaring_bitmap_to_bitset ( r1 , bitset );
assert ( success ); // could fail due to memory allocation.
assert ( bitset_count ( bitset ) == roaring_bitmap_get_cardinality ( r1 ));
// You can then query the bitset:
for ( uint32_t i = 100 ; i < 100000 ; i += 1 + ( i % 5 )) {
assert ( bitset_get ( bitset , i ));
}
for ( uint32_t i = 100000 ; i < 500000 ; i += 100 ) {
assert ( bitset_get ( bitset , i ));
}
// you must free the memory:
bitset_free ( bitset );
roaring_bitmap_free ( r1 );
您應該意識到,在某些情況下,約定位集 ( bitset_t *
) 可能比 Roaring 位圖使用更多的記憶體。您應該執行基準測試來確定轉換為位元集在您的情況下是否具有效能優勢。
此範例假設 CRoaring 已建置並且您正在連結相應的庫。預設情況下,CRoaring 會將其頭檔安裝在roaring
目錄中,因此您可能需要將#include "roaring.hh"
替換為#include <roaring/roaring.hh>
。如果您使用合併腳本工作,並且沒有連結到 CRoaring 預先建立庫,則可以新增#include "roaring.c"
行。
# include < iostream >
# include " roaring.hh "
using namespace roaring ;
int main () {
Roaring r1;
for ( uint32_t i = 100 ; i < 1000 ; i++) {
r1. add (i);
}
// check whether a value is contained
assert (r1. contains ( 500 ));
// compute how many bits there are:
uint32_t cardinality = r1. cardinality ();
// if your bitmaps have long runs, you can compress them by calling
// run_optimize
uint32_t size = r1. getSizeInBytes ();
r1. runOptimize ();
// you can enable "copy-on-write" for fast and shallow copies
r1. setCopyOnWrite ( true );
uint32_t compact_size = r1. getSizeInBytes ();
std::cout << " size before run optimize " << size << " bytes, and after "
<< compact_size << " bytes. " << std::endl;
// create a new bitmap with varargs
Roaring r2 = Roaring::bitmapOf ( 5 , 1 , 2 , 3 , 5 , 6 );
r2. printf ();
printf ( " n " );
// create a new bitmap with initializer list
Roaring r2i = Roaring::bitmapOfList ({ 1 , 2 , 3 , 5 , 6 });
assert (r2i == r2);
// we can also create a bitmap from a pointer to 32-bit integers
const uint32_t values[] = { 2 , 3 , 4 };
Roaring r3 ( 3 , values);
// we can also go in reverse and go from arrays to bitmaps
uint64_t card1 = r1. cardinality ();
uint32_t *arr1 = new uint32_t [card1];
r1. toUint32Array (arr1);
Roaring r1f (card1, arr1);
delete[] arr1;
// bitmaps shall be equal
assert (r1 == r1f);
// we can copy and compare bitmaps
Roaring z (r3);
assert (r3 == z);
// we can compute union two-by-two
Roaring r1_2_3 = r1 | r2;
r1_2_3 |= r3;
// we can compute a big union
const Roaring *allmybitmaps[] = {&r1, &r2, &r3};
Roaring bigunion = Roaring::fastunion ( 3 , allmybitmaps);
assert (r1_2_3 == bigunion);
// we can compute intersection two-by-two
Roaring i1_2 = r1 & r2;
// we can write a bitmap to a pointer and recover it later
uint32_t expectedsize = r1. getSizeInBytes ();
char *serializedbytes = new char [expectedsize];
r1. write (serializedbytes);
// readSafe will not overflow, but the resulting bitmap
// is only valid and usable if the input follows the
// Roaring specification: https://github.com/RoaringBitmap/RoaringFormatSpec/
Roaring t = Roaring::readSafe (serializedbytes, expectedsize);
assert (r1 == t);
delete[] serializedbytes;
// we can iterate over all values using custom functions
uint32_t counter = 0 ;
r1.iterate(
[]( uint32_t value, void *param) {
*( uint32_t *)param += value;
return true ;
},
&counter);
// we can also iterate the C++ way
counter = 0 ;
for (Roaring::const_iterator i = t. begin (); i != t. end (); i++) {
++counter;
}
// counter == t.cardinality()
// we can move iterators to skip values
const uint32_t manyvalues[] = { 2 , 3 , 4 , 7 , 8 };
Roaring rogue ( 5 , manyvalues);
Roaring::const_iterator j = rogue. begin ();
j. equalorlarger ( 4 ); // *j == 4
return EXIT_SUCCESS;
}
CRoring 遵循標準的 cmake 工作流程。從專案的根目錄(CRoaring)開始,您可以執行以下操作:
mkdir -p build
cd build
cmake ..
cmake --build .
# follow by 'ctest' if you want to test.
# you can also type 'make install' to install the library on your system
# C header files typically get installed to /usr/local/include/roaring
# whereas C++ header files get installed to /usr/local/include/roaring
(您可以將build
目錄替換為任何其他目錄名稱。)預設情況下,所有測試都在所有平台上構建,若要跳過建置和執行測試,請在命令列中新增-DENABLE_ROARING_TESTS=OFF
。
與所有cmake
專案一樣,您可以透過新增(例如) -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
到cmake
命令列來指定要使用的編譯器。
如果您使用 clang 或 gcc 並且知道目標架構,則可以透過指定-DROARING_ARCH=arch
來設定架構。例如,如果您有許多伺服器,但最舊的伺服器正在運行 Intel haswell
架構,您可以指定 - DROARING_ARCH=haswell
。在這種情況下,生成的二進位檔案將針對具有 haswell 進程特性的處理器進行最佳化,並且可能無法在舊架構上運行。您可以輸入man gcc
來找到有效體系結構值的清單。
mkdir -p build_haswell
cd build_haswell
cmake -DROARING_ARCH=haswell ..
cmake --build .
對於調試版本,從專案的根目錄(CRoaring)開始,嘗試
mkdir -p debug
cd debug
cmake -DCMAKE_BUILD_TYPE=Debug -DROARING_SANITIZE=ON ..
ctest
若要檢查您的程式碼是否遵守樣式約定(確保安裝了clang-format
):
./tools/clang-format-check.sh
若要根據樣式約定重新格式化程式碼(確保安裝了clang-format
):
./tools/clang-format.sh
我們假設您有一台至少裝有 Visual Studio 2015 的普通 Windows PC 和 x64 處理器。
若要從命令列至少使用 Visual Studio 2015 進行建置:
cmake
。VisualStudio
。CRoaring
,選擇Open in Git Shell
,然後在新建立的 shell 中鍵入cd VisualStudio
。VisualStudio
儲存庫中的 shell 中鍵入cmake -DCMAKE_GENERATOR_PLATFORM=x64 ..
。 (或者,如果您想要建立靜態庫,您可以使用命令列cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DROARING_BUILD_STATIC=ON ..
)RoaringBitmap.sln
)。在 Visual Studio 中開啟此文件。現在您應該能夠建立專案並運行測試。例如,在Solution Explorer
視窗(可從View
功能表存取)中,以滑鼠右鍵按一下ALL_BUILD
並選擇Build
。若要測試程式碼,仍然在Solution Explorer
視窗中,選擇RUN_TESTS
並選擇Build
。若要直接在 IDE 中直接使用 Visual Studio 2017 進行建置:
Visual C++ tools for CMake
。File > Open > Folder...
開啟 CRoring 資料夾。Solution Explorer
中父目錄中的CMakeLists.txt
,然後選擇Build
以產生項目。Select Startup Item...
功能表並選擇其中一項測試。按下拉列表左側的按鈕執行測試。我們在程式碼中針對 AVX2 和 AVX-512 進行了最佳化,並且它們會根據運行時偵測到的硬體進行動態調整。
conan
)您可以安裝預先建置的二進位檔案以進行roaring
,也可以使用 Conan 從原始程式碼建置它。使用以下命令安裝最新版本:
conan install --requires="roaring/[*]" --build=missing
有關如何使用 Conan 的詳細說明,請參閱 Conan 文件。
柯南維護者和社群貢獻者會不斷更新roaring
柯南配方。如果版本已過時,請在 ConanCenterIndex 儲存庫上建立問題或拉取要求。
vcpkg
) Windows、Linux 和 macOS 上的 vcpkg 使用者可以使用他們最喜歡的 shell 中的一個命令下載並安裝roaring
。
在 Linux 和 macOS 上:
$ ./vcpkg install roaring
將建置並安裝roaring
作為靜態函式庫。
在 Windows(64 位元)上:
.vcpkg.exe install roaring:x64-windows
將建置並安裝roaring
作為共用庫。
.vcpkg.exe install roaring:x64-windows-static
將建置並安裝roaring
作為靜態函式庫。
這些命令也會列印如何使用 MSBuild 或基於 CMake 的專案中的程式庫的說明。
如果您發現vcpkg
附帶的roaring
版本過時,請隨時透過提交問題或建立 PR 的方式向vcpkg
社群報告。
我們的 AVX2 程式碼不使用浮點數或乘法,因此它不受多核心英特爾處理器上睿頻頻率限制的影響。
我們的 AVX-512 程式碼僅在最新的硬體(Intel Ice Lake 或更好的以及 AMD Zen 4)上啟用,其中未觀察到 SIMD 特定的頻率限制。
例如,與 STL 容器一樣,CRoaring 庫沒有內建執行緒支援。因此,每當您在一個線程中修改位圖時,在其他線程中查詢它是不安全的。但是,您可以安全地複製位圖並使用兩個副本