A Batched GPU Algorithm for Set Intersection

Similar documents
Efficient Lists Intersection by CPU- GPU Cooperative Computing

Using Graphics Processors for High Performance IR Query Processing

Optimization solutions for the segmented sum algorithmic function

ACCELERATING SELECT WHERE AND SELECT JOIN QUERIES ON A GPU

Scan Primitives for GPU Computing

Efficient Stream Reduction on the GPU

Parallelizing Inline Data Reduction Operations for Primary Storage Systems

Cost Optimal Parallel Algorithm for 0-1 Knapsack Problem

Warps and Reduction Algorithms

CUDA Optimizations WS Intelligent Robotics Seminar. Universität Hamburg WS Intelligent Robotics Seminar Praveen Kulkarni

Fast BVH Construction on GPUs

Fast Snippet Generation. Hybrid System

X10 specific Optimization of CPU GPU Data transfer with Pinned Memory Management

Optimization of Linked List Prefix Computations on Multithreaded GPUs Using CUDA

A Fast and High Throughput SQL Query System for Big Data

Recent Advances in Heterogeneous Computing using Charm++

GPU Implementation of a Multiobjective Search Algorithm

Parallelizing FPGA Technology Mapping using GPUs. Doris Chen Deshanand Singh Aug 31 st, 2010

New research on Key Technologies of unstructured data cloud storage

Correlation based File Prefetching Approach for Hadoop

arxiv: v1 [cs.dc] 24 Feb 2010

THE COMPARISON OF PARALLEL SORTING ALGORITHMS IMPLEMENTED ON DIFFERENT HARDWARE PLATFORMS

Job Re-Packing for Enhancing the Performance of Gang Scheduling

Optimizing Data Locality for Iterative Matrix Solvers on CUDA

GPU Sparse Graph Traversal

Matrox Imaging White Paper

CS24: INTRODUCTION TO COMPUTING SYSTEMS. Spring 2017 Lecture 15

OVERHEADS ENHANCEMENT IN MUTIPLE PROCESSING SYSTEMS BY ANURAG REDDY GANKAT KARTHIK REDDY AKKATI

A Study on Load Balancing Techniques for Task Allocation in Big Data Processing* Jin Xiaohong1,a, Li Hui1, b, Liu Yanjun1, c, Fan Yanfang1, d

Improved Integral Histogram Algorithm. for Big Sized Images in CUDA Environment

Optimizing Energy Consumption and Parallel Performance for Static and Dynamic Betweenness Centrality using GPUs Adam McLaughlin, Jason Riedy, and

Parallel Prefix Sum (Scan) with CUDA. Mark Harris

GPU-accelerated data expansion for the Marching Cubes algorithm

OPENCL GPU BEST PRACTICES BENJAMIN COQUELLE MAY 2015

Best Practices. Deploying Optim Performance Manager in large scale environments. IBM Optim Performance Manager Extended Edition V4.1.0.

CS377P Programming for Performance GPU Programming - II

Lecture 13: March 25

Text Analytics. Index-Structures for Information Retrieval. Ulf Leser

A distributed in-memory key-value store system on heterogeneous CPU GPU cluster

TUNING CUDA APPLICATIONS FOR MAXWELL

CS 314 Principles of Programming Languages

Data-Parallel Algorithms on GPUs. Mark Harris NVIDIA Developer Technology

Preliminary Research on Distributed Cluster Monitoring of G/S Model

Efficient Decoding of Posting Lists with SIMD Instructions

CSE 4/521 Introduction to Operating Systems. Lecture 23 File System Implementation II (Allocation Methods, Free-Space Management) Summer 2018

A priority based dynamic bandwidth scheduling in SDN networks 1

CUDA (Compute Unified Device Architecture)

6.2 DATA DISTRIBUTION AND EXPERIMENT DETAILS

Data Parallel Programming with Patterns. Peng Wang, Developer Technology, NVIDIA

Applications of Berkeley s Dwarfs on Nvidia GPUs

Manycore Processors. Manycore Chip: A chip having many small CPUs, typically statically scheduled and 2-way superscalar or scalar.

More on Conjunctive Selection Condition and Branch Prediction

An Empirically Optimized Radix Sort for GPU

Advanced Database Systems

Research on the Application of Bank Transaction Data Stream Storage based on HBase Xiaoguo Wang*, Yuxiang Liu and Lin Zhang

A Parallel Access Method for Spatial Data Using GPU

High Performance Computing on GPUs using NVIDIA CUDA

Research and Application of E-Commerce Recommendation System Based on Association Rules Algorithm

TUNING CUDA APPLICATIONS FOR MAXWELL

School of Computer and Information Science

Optimizing Out-of-Core Nearest Neighbor Problems on Multi-GPU Systems Using NVLink

GPU Programming. Lecture 1: Introduction. Miaoqing Huang University of Arkansas 1 / 27

GPU Accelerated Machine Learning for Bond Price Prediction

Parallel Variable-Length Encoding on GPGPUs

Preview. Memory Management

On Fast Parallel Detection of Strongly Connected Components (SCC) in Small-World Graphs

Mapping Vector Codes to a Stream Processor (Imagine)

Implementation of Parallel Set Intersection for Keyword Search using RapidMind

GPU Performance Optimisation. Alan Gray EPCC The University of Edinburgh

Operating System Performance and Large Servers 1


Open Access The Three-dimensional Coding Based on the Cone for XML Under Weaving Multi-documents

A TALENTED CPU-TO-GPU MEMORY MAPPING TECHNIQUE

CS 179: GPU Computing LECTURE 4: GPU MEMORY SYSTEMS

Cache Memories. From Bryant and O Hallaron, Computer Systems. A Programmer s Perspective. Chapter 6.

Presented by: Nafiseh Mahmoudi Spring 2017

Text Analytics. Index-Structures for Information Retrieval. Ulf Leser

Efficient Tridiagonal Solvers for ADI methods and Fluid Simulation

Clustering and Reclustering HEP Data in Object Databases

A Software LDPC Decoder Implemented on a Many-Core Array of Programmable Processors

3D ADI Method for Fluid Simulation on Multiple GPUs. Nikolai Sakharnykh, NVIDIA Nikolay Markovskiy, NVIDIA

GPU ACCELERATED DATABASE MANAGEMENT SYSTEMS

Accelerating Leukocyte Tracking Using CUDA: A Case Study in Leveraging Manycore Coprocessors

Accelerating Lossless Data Compression with GPUs

GPGPUs in HPC. VILLE TIMONEN Åbo Akademi University CSC

A PERFORMANCE COMPARISON OF SORT AND SCAN LIBRARIES FOR GPUS

GPU Multisplit. Saman Ashkiani, Andrew Davidson, Ulrich Meyer, John D. Owens. S. Ashkiani (UC Davis) GPU Multisplit GTC / 16

OPERATING SYSTEM. PREPARED BY : DHAVAL R. PATEL Page 1. Q.1 Explain Memory

Indexing and Searching

Stream Processing with CUDA TM A Case Study Using Gamebryo's Floodgate Technology

An Efficient AC Algorithm with GPU

Lecture 13: Memory Consistency. + a Course-So-Far Review. Parallel Computer Architecture and Programming CMU , Spring 2013

Dynamic Fine Grain Scheduling of Pipeline Parallelism. Presented by: Ram Manohar Oruganti and Michael TeWinkle

Fast Segmented Sort on GPUs

Implementing a Statically Adaptive Software RAID System

Profiling-Based L1 Data Cache Bypassing to Improve GPU Performance and Energy Efficiency

A Cache Utility Monitor for Multi-core Processor

Chapter 12: File System Implementation

ACCELERATING THE PRODUCTION OF SYNTHETIC SEISMOGRAMS BY A MULTICORE PROCESSOR CLUSTER WITH MULTIPLE GPUS

Coordinating More Than 3 Million CUDA Threads for Social Network Analysis. Adam McLaughlin

Transcription:

A Batched GPU Algorithm for Set Intersection Di Wu, Fan Zhang, Naiyong Ao, Fang Wang, Xiaoguang Liu, Gang Wang Nankai-Baidu Joint Lab, College of Information Technical Science, Nankai University Weijin Road 94, Tianjin, 371, China Email: {wakensky,zhangfan555}@gmail.com, aonaiyong@163.com, wangfang9@gmail.com, liuxg74@yahoo.com.cn, wgzwp@163.com Abstract Intersection of inverted lists is a frequently used operation in search engine systems. Efficient CPU and GPU intersection algorithms for large problem size are well studied. We propose an efficient GPU algorithm for high performance intersection of inverted index lists on CUDA platform. This algorithm feeds queries to GPU in batches, thus can take full advantage of GPU processor cores even if problem size is small. We also propose an input preprocessing method which alleviate load imbalance effectively. Our experimental results based on a real world test set show that the batched algorithm is much faster than the fastest CPU algorithm and plain GPU algorithm. I. INTRODUCTION The Internet search market has undergone a booming expansion along with the rapid growth of Internet, which makes search engines faced with great performance challenges. To provide high throughput, search engine systems typically are built upon large-scale clusters. Nevertheless, per node workload is still quite heavy, especially CPU occupancy is high. Thus, in order to maximize overall throughout, we propose a new approach to offload the CPU workload to graphical processing units (GPUs). In search engine systems, list intersection occupies a significant part of CPU time. A search query is composed of several keywords. Each keyword corresponds to an inverted index list which stores IDs of documents that contain this keyword. What search engine returns to user is just the intersection result of the inverted index lists involved. The data set we used is provided by Baidu Inc. It is a real world test set instead of a synthetic one. It contains 33337 user search queries. Each query contains 2 to 8 keywords. Our aim is to offload all intersection calculation from CPU to GPU. However, our data set has a property: most of inverted index lists are short (contain less than 1, docids). That is to say, problem size is small generally. To the best of our knowledge, no previous work focuses on GPU algorithm for this type of input. However, we believe that small problem size is a common character of real search engine systems, because most of user queries contain multi-keyword. The intermediate result might become smaller after first one or two intersections. Our contributions mainly deal with this property: 1) We design a batched GPU algorithm. The experimental results show that for small queries, this new algorithm is far superior to other GPU algorithms. 2) We design an input preprocessing method to get the best performance of our algorithm. 3) Tradeoff between throughout and response time is considered. II. RELATED WORK List intersection is well studied in these years because of its importance in search engines. Some important results are published [1, 5, 6, 7]. But most of them perform well only for large lists. Generally, document IDs in a list are sorted. So an intuitive GPU algorithm for intersection operation of two lists is: each thread fetches one element from the shorter list, then all threads do binary search in the longer list simultaneously and independently. However, if the two lists are both very large (say, both contain millions of elements), quite a lot compare operations are wasteful. Thus an improvement called partition is presented in [1]. The shorter list is divided into several segments, and the last element of each segment is searched in the longer list by a unique thread. Whether the representative element is found or not, its segment is confined to a subregion of the longer list. Fig. 1 illustrates this idea. After partition, each segment in the shorter list corresponds to a segment in the longer list. The number of compare operations decreases dramatically. short list 1, 3, 5, 7 9, 12, 16, 2 25, 28 1, 2, 3, 5, 6, 7 8, 13, 15, 16, 17, 18, 19 26, 3, 32 Fig. 1. long list Partition parallel algorithm. As experimental results shown in [1], when the length of lists is larger than 1K, partition algorithm is about 4 times faster than simple binary algorithm. However, the data set we deal with contains a lot of short lists, so the overhead of partition stage may cancel out its gain. Our experimental results confirmed this conjecture. The CPU algorithm we use for comparison is designed by Ling Jiang, Baidu Inc. It is specially optimized for our data set. As Fig. 2 presents, the longer list is divided into several segments all of equal length. Each element of shorter list is searched in the longer list sequentially, however, the step is one segment instead of one element. If the element is greater than the last element of the current segment, we move to the next segment. Otherwise, we turn around to search backwards in the current segment.

segment ele Fig. 2. if larger then turn around Stride sequential algorithm. III. ARCHITECTURE segment5 We start out with a typical CPU single stream model. Whenever a search query arrives, CPU puts it in the process queue. It is starting to be processed when the predecessor query is completed. We can convert this model into GPU processing model simply by offloading each intersection calculation to GPU. CPU hands over the query which it receives to GPU, then waits until GPU returns the result. This simple GPU model is just that we used in our preliminary work, called Serial GPU model. However, this model can not take full advantage of GPU s computing power when queries are short. Fig. 3 shows the improved model. In order to make hundreds of GPU shaders busy, queries are pumped to GPU in batches instead of one by one. In this model, CPU is only in charge of task scheduling and data transfering. All calculation tasks are offloaded to GPU. intersection of the result array and the third shortest list, and so on. 3) Write the length of final result array to a predefined global memory location, so CPU can fetch the result. The most time consuming part of the whole procedure is step 2. It is composed of three steps: 1) Search: Each thread fetches some elements in the shorter list, then do binary searches in the longer list. If an element is found, its corresponding cell in a temporary array is set to 1 (this array is zeroed when initializing). 2) Scan: We perform a scan (prefix sum) operation on the -1 array, so we get the locations of common elements of the two lists in the result array. There are some considerations for scan phase: a) The number of threads per block is fixed, so we must divide the whole -1 array into several segments. Each segment contains the same number of elements as the number of threads. The last segment may be an incomplete segment. We deal with it specially. b) An efficient scan algorithm must be adopted, as scan is a frequent operation in the whole procedure. The scan algorithm we adopted is based on the algorithm presented by Hillis and Steele[2], showed in Fig. 4. x x1 x2 x3 x4 x5 x6 x7 Step Internet user queries CPU shedule GPU kernel call One by one --------------------- Batch transfer ------------------ Make batch Batched process in parallel x x x:x1 x1:x2 x2:x3 x3:x4 x4:x5 x5:x6 x6:x7 x:x1 x:x2 x:x3 x1:x4 x2:x5 x3:x6 x4:x7 Step 1 Step 2 Fig. 3. Batched GPU model. x x:x1 x:x2 x:x3 x:x4 x:x5 x:x6 x:x7 Step 3 The schedule procedure consists of four steps: 1) Transfer inverted index lists to GPU memory. If the size of data set is smaller than the capacity of GPU memory, only one transfer operation is performed. 2) Prepare query batch. CPU waits n queries arrive, pack them into one batch, then calls the GPU function (GPU kernel) to calculate. 3) GPU runs the kernel function to perform list intersection, and then writes the result to a buffer. 4) The result is transferred back to main memory. Our main work is to refine step 3. We assign each query to a unique block. So, n blocks all contain t threads, where t depends on the size of input. If all inverted index lists are large, we need more threads per block. So step 3 is refined as: 1) Find the corresponding inverted index lists according to the key words in the query. We sort these inverted index lists by length in ascending order. If perform intersection in this order, there is a strong possibility of achieving optimal computational complexity. 2) Intersection. First, we calculate the intersection of the shortest list and the second shortest list. The result is stored in a result array. Then we calculate the Fig. 4. Scan algorithm. The main part of the algorithm is a loop. In each iteration, the i-th element is added to the (i + offset)- th element. Offset is initialized as 1, and is doubled after each iteration. We can see that this algorithm calculates inclusive prefix sum. We can see that if -1 array contains N elements, the loop will finish after log(n) steps. The j-th iteration performs N 2j 1 add operations. Thus the algorithm performs Nlog(N) (N 1) add operations in total. In order to avoid memory copy, we allocate two buffers both of length N. They are both allocated in shared memory which is much faster and smaller than global memory. After finishing calculating the first segment, we copy the result from shared memory back to global memory. Next we copy the last element of each result segment to the first location in the next segment. Then this element is added to every other element in the second segment. Then the same operation is performed on the second segment and its successor segment, and so on. So the global scan result is calculated correctly. This algorithm is called naive algorithm [2]. Although other algorithms exist [2], our

experimental results show that this simple algorithm is the best for our data set. 3) Compacting: each thread is in charge of several elements in the shorter inverted index list. If the corresponding element in -1 array is 1, the thread should store the element into the result array. The corresponding element in the scan result designates the right position of this element in the result array. Fig. 5 illustrates the whole procedure of step 2. Data Data1 Data2 Data3 Data4 Data5 Data6 Data7 index list 1 1 1 1 1 1 2 3 3 3 4 4 Data Data2 Data3 Data6 Fig. 5. Calculate final position in result array. -1 array Scan result Result array (compacted) We also implemented an algorithm based on the serial GPU model for comparison. Namely, queries are delivered to GPU one by one. To maximize the degree of parallelism, each intersection operation is processed by multiple blocks, and each thread is in charge of only one element in the shorter list. For example, there are 1271 elements in the shorter list and 128 threads per block, so we will deploy 1 blocks when we call the GPU kernel function. The scan routine used in this algorithm is cudppscan from cudpp library. The compacting step is the same as that in batched algorithm. IV. EXPERIMENTAL RESULTS Our experiments are based on CUDA platform version 2.3, detailed experimental results are listed below. Host: Intel i7 92 CPU, 2GB 2 DDR3 1333 memory. GPU: Nvidia Tesla C16, which has 3 streaming multiprocessors, 24 scalar processor cores in total. The frequency of processor cores is 1.3GHz. The card is equipped with 4GB DDR3 memory of bandwidth 12GB/s. Bandwidth between GPU memory and main memory is about 5.13 GB/s. The number of threads per block is fixed at 128. The inverted index lists are stored in one file, named ind data, which occupies 86MB disk space. As it is smaller than 4GB, so we upload it into GPU memory once. It takes 188.8ms. Host-GPU bandwidth occupancy is about 88.8%. The test data includes 33337 search queries, and we simulate it as a query stream comes into search server in short time. Since the test data is a fraction of actual search query stream, the workload of each query is quite random, which is an important influence factor to GPU response time. CPU schedules the queries to GPU, and fetches the result after GPU finishes its work. Fig. 6 shows the distribution of the length of shortest inverted index lists of queries. When we refer to shortest, we mean that it is the shortest list in its query. For example, query has six key words, which are corresponding to six inverted index lists. We can select the shortest list out. So, we will have 33337 shortest inverted index lists in total. Since queries have been uploaded to GPU memory, the sort of each query is implemented with only one GPU thread. The number of lists in one query is less than 8, so we adopt insertion sort algorithm. While the procedure of sort, other threads are all waiting. Our experimental results show that the overhead of this step occupies only 2ms in total. The length of the shortest list 1K+ 9K-1K 8K-9K 7K-8K 6K-7K 5K-6K 4K-5K 3K-4K 2K-3K 1K-2K 9K-1K 8K-9K 7K-8K 6K-7K 5K-6K 4K-5K 3K-4K 2K-3K 1K-2K -1K 114 1 18 57 43 18 127 319 611 1538 294 438 449 586 682 94 1292 192 354 Fig. 6. The number of queries Query size distribution. The length of the shortest list reflects the workload of the query directly. For example, the length of the shortest list in query is 259, so after five intersections, the length of result array is smaller or equal to 259. We can see that 91% of shortest lists in our data set are shorter than 1k docids. We now perform a preliminary evaluation of our two GPU models. The queries are delivered to GPU according to their original order in file test data. In the serial processing model, we deploy 128 threads per block. Thus for 77.2% queries, at most 3 blocks are invoked. Tesla C16 has 3 multiprocessors, so the workload can not feed it. Fig. 7 shows the runtime of the two algorithms. We can see that the batched algorithm is obviously superior to the plain algorithm because it utilizes more processor cores. When the size of batch is larger than 8192, the runtime remain stable at about 316ms. 4 35 3 25 2 15 1 5 33337 16384 8192 496 248 124 512 256 Fig. 7. batch size Original order result. TABLE I shows the performance gap between the CPU algorithm and the batched GPU algorithm. The CPU program is still much faster than the GPU one. Further examination on the data set exposes serious load imbalance. If queries are fed to GPU in their original order in test data, the queries in a batch will vary in size. Therefore when some queries have completed, other queries may be still 2323 serial batch

TABLE I ORIGINAL ORDER RUNTIME ON CPU AND GPU. calculating time (ms) GPU batch model (test data) 316 CPU (test data) 1569 faster than CPU algorithm for all buckets. As the batch size decreases to 64, the runtime increases. The reason is that 64 queries can not take full advantage of GPU. CPU GPU(512 per batch) GPU(64 per batch) in process. Since a batch is processed by a single kernel call and current CUDA version can not execute multiple kernels simultaneously, perhaps only a minority of GPU processor cores are busy in the later stages of query processing. Besides, the different number of key words is also the reason for load imbalance. The main objective of batched algorithm - making full use of GPU processor cores - fails. To solve the problem, we must pack the queries of similar size into a batch. We can estimate the problem size of each query by the length of its shortest list. Our experimental results shows that this estimation is reasonable. How to find queries of similar size? Sorting queries completely by size is unpractical. We adopted semi-sort: divide the range of list length into several buckets and assign each query to a bucket according to the length of its shortest list. In general, Here comes n queries which will be allocated into c buckets, each of them needs c-1 comparison times at most. This preprocessing is implemented by CPU, and is a linear time operation. Compared with complete sorting, this method introduces much lower overhead. Certainly, we will divide a big bucket into multiple batches. We performed this preprocess on our data set. The length range is divided into 2 buckets. -1K is divided into 1 buckets all of interval 1K, and 1K-1K is divided into 1 buckets all of interval 1K. Then we test the CPU algorithm and the two GPU algorithms using this rearranged test data. For batched GPU algorithm, batch size is set to 16384. Fig. 8 shows the result. We can see that new input order improves the performance of batched GPU algorithm dramatically. GPU batched algorithm spent 421 ms on calculating and 15 ms on dynamic transfer. It decreases calculating time 6 times compared with the unordered input. Now, batched GPU algorithm is 2.7x faster than CPU algorithm, and 5.2x faster than plain GPU algorithm. 4 35 3 25 2 15 1 5 Fig. 8. GPU serial CPU GPU batch GPU batch w/ transfer w/o time transfer time Runtime on ordered input. We also test CPU algorithm and batched algorithm using individual bucket. Each bucket is divided into batches of fixed length. The result is shown in Fig. 9. We can see that if the number of queries per batch is over 512, GPU algorithm is 25 2 15 1 5 Fig. 9. Query size Runtime on single bucket. Since the batch size (equals to the number of blocks per GPU kernel call) influences the performance greatly, we tested batched GPU algorithm using different batch sizes. The whole data set instead of individual buckets is used. Fig. 1 shows the result. We can see that the algorithm always exhibits good performance unless the batch size is extremely small (32). It achieves peak performance at 124 and holds the line as the batch size continues to increase. 16 14 12 1 8 6 4 2 Fig. 1. Batch Size Runtime of different batch size. calculating time dynamic transfer time There are three data transfer steps in the batched algorithm: 1) Transfer inverted index lists to GPU memory. In our case, all lists can be stored in GPU memory, so this type of transfer needs once only. We call it static transfer overhead. Step 2 and 3 are called dynamic transfer overhead. 2) Transfer queries onto GPU memory. The transfer must be invoked before every GPU kernel call. Since the space occupancy of queries is quite small (all 33337 queries only occupy 549KB), so it induces a light overhead. 3) Transfer result arrays back to main memory. There are two methods for the task: a) Transfer result arrays separately. For example, there are 128 queries in the batch applied to GPU. When GPU kernel function returns, we invoke 128 times cudamemcpy to fetch the result respectively. b) Transfer result arrays at a time. A large result array will be allocated on GPU memory before each GPU kernel call, whose size is the length sum of the size of all shortest lists in this batch. It is sufficient for GPU to use as the intersection result is shorter than the length of the shortest list. However, memory space is wasted. For example, sum

the length of shortest list is 1271, while the intersection result contains only 125 docids. Now we still need transfer 1271 docids and allocate 1271 docids memory space to receive the result. The transfer time is not only determined by the size of data, but also be influenced significantly by the number of transfer operations. TABLE II compares the performance of these two transfer methods. The batch size is set to 248. There exists dramatic performance gap between the two methods. If we transfer the result one by one, transfer overhead will cancel out the advantage of batched processing. So the best method is to transfer all results together, despite some memory space is wasted. Fig. 1 shows the detailed dynamic transfer time under different batch sizes. We can see that the transfer time is only a small part of total time. TABLE II TRANSFER TIME OF THE TWO METHODS. time used by step 2 and 3 (ms) transfer separately 461.6 transfer as a whole 155.1 Besides the total calculating time and total dynamic transferring time, the response time of each batch is also an important factor we care about. For example, if batch size is 16384, there are 3 batches. The total calculation time is 421ms, and the total transferring time is 15ms. So, each batch takes about 19ms. It means that the response time is about 19ms which is obviously not acceptable. Fig.11 shows the response time curve when batch size varies. Response time (ms) 512 256 128 64 32 16 8 4 2 1 32 64 128 256 512 124 248 496 8192 1638432768 Fig. 11. the number of queries per batch Response time. We believe that GPUs will play an important role in actual large-scale distributed systems such as search engines in the future. However, a lot of work needs to be done to make our algorithm more practical. Our experiments are all performed off line. Designing an online input preprocessing algorithm is an important future work. Since the data set in real search engine systems may be much larger than our test set, a streamed GPU algorithm should be developed to hide transfer overhead. Multi-GPU algorithm is also an interesting topic. VI. ACKNOWLEDGMENT This paper is supported partly by the National High Technology Research and Development Program of China (28AA1Z41), NSFC of China (69328), SRFDP of China (275554), and Science and Technology Development Plan of Tianjin (8JCYBJC13). We would like to thank Baidu Inc. to provide data set and other necessary materials. Many thanks to Guangjun Xie for his kindly help. Thank Ling Jiang for providing the efficient CPU algorithm. We also must thank Hao Yan for providing related code. REFERENCES [1] S. Ding, J. He, H. Yan, and T. Suel, Using Graphics Processors for High Performance IR Query Processing, in WWW 29, April 2-24, 29, Madrid, Spain. [2] M. Harris, Parallel prefix sum (scan) with CUDA,, www.nvidia.com, April 27. [3] Nvidia CUDA programming guide 2.1, http://www.nvidia.com/object/cuda develop.html. [4] S. Sengupta, M. Harris, and M. Garland, Ecient Parallel Scan Algorithms for GPUs, NVIDIA Technical Report, NVR-28-3, Dec. 28. [5] E. D. Demaine, A. Lopez-Ortiz, and J. I. Munro, adaptive set intersections,unions,and differences, Eleventh ACM-SIAM Symposium on Discrete Algorithms, 2. [6] F. Samuel, J. Barbay, and M. McCool, Implementation of Parallel Set Intersection for Keyword Search using RapidMind, University of Waterloo Technical Report, CS-27-12. [7] G. E. Blelloch, and M. Reid-Miller, Fast Set Operations Using Treaps, 1th Annual ACM Symposium on Parallel Algorithms and Architectures, SPAA 98. [8] N. Satish, M. Harris, and M. Garland, Designing Effcient Sorting Algorithms for Manycore GPUs, in 23rd IEEE International Parallel and Distributed Processing Symposium, May 29. [9] NVIDIA CUDA C Programming Best Practices Guide, http://www.nvidia.com/object/cuda develop.html. Compared with Fig. 1 and Fig. 11, we can determine the best choice of batch size. On our data set, 124 or 248 queries per batch will achieve the good tradeoff between throughput and response time. V. CONCLUSION We have proposed an efficient GPU algorithm for high performance intersection of inverted index lists. This algorithm fed enough queries to GPU in batch, thus takes full advantage of GPU processor cores. We also proposed an input preprocessing method which alleviates load imbalance effectively. Our experimental results based on a real world test set show that the batched algorithm is much faster than the fastest CPU algorithm and plain GPU algorithm.