1- #include < cuco/detail/error.hpp>
1+ /*
2+ * Copyright (c) 2025 NVIDIA CORPORATION.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
216#include < cuco/roaring_bitmap.cuh>
17+ #include < cuco/utility/traits.hpp>
318
4- #include < cuda/std/span>
19+ #include < cuda/std/type_traits>
20+ #include < thrust/device_vector.h>
521#include < thrust/logical.h>
622#include < thrust/universal_vector.h>
723
8- #include < cuda_runtime.h>
9-
1024#include < fstream>
1125#include < iostream>
26+ #include < string>
1227#include < vector>
1328
14- int main (int argc, char * argv[])
29+ /* *
30+ * @file host_bulk_example.cu
31+ * @brief Demonstrates usage of the roaring_bitmap "bulk" lookup host APIs.
32+ *
33+ * In this example we load two 32-bit bitmaps and one 64-bit bitmap (portable format) from the
34+ * [RoaringBitmapFormatSpec](https://github.com/RoaringBitmap/RoaringFormatSpec) repository and
35+ * check if the bulk lookup API returns the correct results. Namely, we test the following files:
36+ * -
37+ * [examples/roaring_bitmap/bitmapwithoutruns.bin](https://github.com/RoaringBitmap/RoaringFormatSpec/blob/master/testdata/bitmapwithoutruns.bin)
38+ * -
39+ * [examples/roaring_bitmap/bitmapwithruns.bin](https://github.com/RoaringBitmap/RoaringFormatSpec/blob/master/testdata/bitmapwithruns.bin)
40+ * -
41+ * [examples/roaring_bitmap/portable_bitmap64.bin](https://github.com/RoaringBitmap/RoaringFormatSpec/blob/master/testdata64/portable_bitmap64.bin)
42+ *
43+ */
44+
45+ template <typename KeyType>
46+ bool check (std::string const & bitmap_file_path)
1547{
16- if (argc != 2 ) {
17- std::cerr << " Usage: " << argv[0 ] << " <bitmap_file_path>" << std::endl;
18- return -1 ;
19- }
48+ auto generate_keys = []() -> thrust::device_vector<KeyType> {
49+ if constexpr (cuda::std::is_same_v<KeyType, cuda::std::uint32_t >) {
50+ // reference:
51+ // https://github.com/RoaringBitmap/RoaringFormatSpec/blob/master/testdata/README.md#test-data
52+ std::vector<cuda::std::uint32_t > keys;
53+ for (cuda::std::uint32_t k = 0 ; k < 100000 ; k += 1000 ) {
54+ keys.push_back (k);
55+ }
56+ for (int k = 100000 ; k < 200000 ; ++k) {
57+ keys.push_back (3 * k);
58+ }
59+ for (int k = 700000 ; k < 800000 ; ++k) {
60+ keys.push_back (k);
61+ }
62+ return thrust::device_vector<cuda::std::uint32_t >(keys.begin (), keys.end ());
63+ } else if constexpr (cuda::std::is_same_v<KeyType, cuda::std::uint64_t >) {
64+ // reference:
65+ // https://github.com/RoaringBitmap/RoaringFormatSpec/blob/master/testdata64/README.md#portable_bitmap64bin
66+ std::vector<cuda::std::uint64_t > keys;
67+ for (cuda::std::uint64_t k = 0x00000ull ; k < 0x09000ull ; ++k) {
68+ keys.push_back (k);
69+ }
70+ for (cuda::std::uint64_t k = 0x0A000ull ; k < 0x10000ull ; ++k) {
71+ keys.push_back (k);
72+ }
73+ keys.push_back (0x20000ull );
74+ keys.push_back (0x20005ull );
75+ for (cuda::std::uint64_t i = 0 ; i < 0x10000ull ; i += 2ull ) {
76+ keys.push_back (0x80000ull + i);
77+ }
78+ return thrust::device_vector<cuda::std::uint64_t >(keys.begin (), keys.end ());
79+ } else {
80+ static_assert (cuco::dependent_false<KeyType>, " KeyType must be uint32_t or uint64_t" );
81+ return {};
82+ }
83+ };
2084
2185 // Open file
22- std::ifstream file (argv[ 1 ] , std::ios::binary);
86+ std::ifstream file (bitmap_file_path , std::ios::binary);
2387 if (!file.is_open ()) {
24- std::cerr << " Failed to open " << argv[ 1 ] << std::endl;
25- return - 1 ;
88+ std::cerr << " Failed to open " << bitmap_file_path << std::endl;
89+ return false ;
2690 }
2791
2892 // Get file size
2993 file.seekg (0 , std::ios::end);
3094 std::streamsize file_size = file.tellg ();
3195 file.seekg (0 , std::ios::beg);
3296
33- // Allocate pinned host memory using cudaMallocHost
34- char * buffer;
35- CUCO_CUDA_TRY (cudaMallocHost (&buffer, file_size));
97+ thrust::universal_host_pinned_vector<cuda::std::byte> buffer (file_size);
3698
3799 // Read file into memory
38- file.read (buffer, file_size);
100+ file.read (reinterpret_cast < char *>( thrust::raw_pointer_cast ( buffer. data ())) , file_size);
39101 file.close ();
40102
41- cuco::roaring_bitmap<cuda::std::uint32_t > roaring_bitmap (
42- reinterpret_cast <cuda::std::byte const *>(buffer));
103+ cuco::roaring_bitmap<KeyType> roaring_bitmap (thrust::raw_pointer_cast (buffer.data ()));
43104
44- std::vector<cuda::std::uint32_t > keys;
45- for (cuda::std::uint32_t k = 0 ; k < 100000 ; k += 1000 ) {
46- keys.push_back (k);
47- }
48- for (int k = 100000 ; k < 200000 ; ++k) {
49- keys.push_back (3 * k);
50- }
51- for (int k = 700000 ; k < 800000 ; ++k) {
52- keys.push_back (k);
53- }
105+ auto keys = generate_keys ();
106+ thrust::device_vector<bool > contained (keys.size (), false );
54107
55- thrust::universal_vector<cuda::std::uint32_t > keys_d (keys.begin (), keys.end ());
56- thrust::universal_vector<bool > contained (keys.size (), false );
108+ roaring_bitmap.contains (keys.begin (), keys.end (), contained.begin ());
57109
58- roaring_bitmap.contains (keys_d.begin (), keys_d.end (), contained.begin ());
110+ bool all_contained = thrust::all_of (contained.begin (), contained.end (), ::cuda::std::identity{});
111+ return all_contained;
112+ }
59113
60- size_t num_errors = 0 ;
61- for (size_t i = 0 ; i < keys.size (); i++) {
62- if (not contained[i]) {
63- if (num_errors <= 10 ) {
64- std::cout << " Error: " << keys_d[i] << " is not contained" << std::endl;
65- }
66- num_errors++;
67- }
68- }
69- if (num_errors > 0 ) { std::cout << " num_errors: " << num_errors << std::endl; }
114+ int main ()
115+ {
116+ auto data_dir_prefix = []() -> std::string {
117+ std::string source_path = __FILE__;
118+ auto pos = source_path.find_last_of (" /\\ " );
119+ return (pos == std::string::npos) ? std::string (" ." ) : source_path.substr (0 , pos);
120+ };
70121
71- // check if all elements are contained and written to output
72- bool all_contained = thrust::all_of (contained. begin (), contained. end (), ::cuda::std::identity{} );
73- std::cout << " all_contained: " << all_contained << std::endl ;
122+ bool success = check<cuda::std:: uint32_t >( data_dir_prefix () + " /bitmapwithoutruns.bin " );
123+ success &= check<cuda::std:: uint32_t >( data_dir_prefix () + " /bitmapwithruns.bin " );
124+ success &= check<cuda:: std::uint64_t >( data_dir_prefix () + " /portable_bitmap64.bin " ) ;
74125
75- // Free the allocated memory
76- CUCO_CUDA_TRY (cudaFreeHost (buffer));
126+ std::cout << " success: " << (success ? " true" : " false" ) << std::endl;
77127
78- return 0 ;
128+ return success ? 0 : 1 ;
79129}
0 commit comments