# Pipeline and Data Parallel Hybrid Indexing Algorithm for Multi-core Platform

Suqing Zhang, Jirui Li

► To cite this version:

Suqing Zhang, Jirui Li. Pipeline and Data Parallel Hybrid Indexing Algorithm for Multi-core Platform. 15th International Conference on Informatics and Semiotics in Organisations (ICISO), May 2014, Shanghai, China. pp.272-280, 10.1007/978-3-642-55355-4_28 . hal-01350933

HAL Id: hal-01350933

https://inria.hal.science/hal-01350933

Submitted on 2 Aug 2016

**HAL** is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_1.png" /></figure>

Distributed under a Creative Commons Attribution 4.0 International License
# Pipeline and Data Parallel Hybrid Indexing Algorithm
## for Multi-core Platform

Suqing Zhang ¹, Jirui Li ²

¹ Information Engineer Department,Henan Vocational and Technical Institute,
Zhengzhou, China
280946342@qq.com

² Information Engineer Department,Henan Vocational and Technical Institute,
Zhengzhou, China
ljrokyes@163.com

**Abstract.** The scale and growth rate of today's text collection bring new challenges for index construction. To tackle this problem, Pipeline and Data Parallel Hybrid Algorithm (PDPH), is proposed to improve the indexing performance for multi-core platform. Compared to existing sequential indexing algorithms, Pipeline and data parallelism are introduced by the PDPH to improve the algorithm flexibility and scale the performance with more cores. Evaluations showed this algorithm can improve index construction speed for multi-core platform.

**Keywords:** Multi-core platform, Indexing Algorithms, Data Parallel, PHPD

## 1 Introduction

The world's data is increasing at an astonishing rate. The scale and growth rate of text collection bring new challenges for index construction. Building an index for a large text collection may involve parsing billions of documents, handling millions of distinct words, and processing billions of occurrences of words in the text. Text collections have become so large and are growing so rapidly that traditional indexing schemes become unmanageable, requiring huge resources and taking days to complete. More powerful computing resources and more efficient algorithms are needed to tackle this problem. T

With the growth of data, the computing power also increases according to Moore's law. Computing power is increasing because of the multi-core technology. Multi-core technology packs two or more execution cores into a single processor so a single chip can provide multiple execution resources. Multi-core architecture is in essence a divide-and-conquer strategy. By divvying up computational work and then spreading it over multiple execution cores, a multi-core processor can perform more work in a given clock cycle than a traditional single core processor. Multi-core processors provide thread-level parallelism. However, to make full use of thread-level parallelism, an application should be threaded so that it can spread its workload across multiple execution cores.
In a multi-core system, there are usually several execution cores, shared memory and disks. However, those existing sequential indexing algorithms, which are mostly single-threaded, treat the multi-core system the same as the traditional single-core system and cannot make use of the multiple execution cores. Also, semiconductor manufacturers of multi-core processors choose to scale back the clock speed so that the chips run cooler, so the performance of single-threaded sequential indexing algorithms in a multi-core system will decrease a little compared with the traditional single-core environment.

We present an efficient indexing algorithm that can be deployed on multi-core systems. It is the Pipeline and Data Parallel Hybrid (PDPH) algorithm. In addition to employing a pipeline, the PDPH algorithm also introduces data parallelism into the indexing process. This algorithm has good performance. It is also more scalable than the existing sequential algorithms.

## 2 Sequential Indexing Algorithms

There are several proposed algorithms to construct index files(inverted files). The Simple In-Memory algorithm keeps all index data in the main memory. It is only suitable for small text collections. The Disk-Based algorithm makes use of temporal files in order to reduce the need for the main memory. However, because there are many random disk accesses, the Disk-Based approach is too slow for large collections. The Two-Pass In-Memory approach introduces compression to limit temporal disk space usage, but it uses two passes over the collections that means it needs to traverse the text collection twice. For large text collections, for example a terabyte scale collection, just traversing the whole collection will take a long time. Both of the Sort-Based algorithm and the Single-Pass algorithm are scalable methods. They can be used for text collections with any size and can work with limited main memory. However, because the Single-Pass algorithm stores compressed index data in memory, it makes better use of memory than the Sort-Based algorithm. Because of this, the Single-Pass algorithm is the most efficient sequential indexing algorithm.

The Single-Pass algorithm travels only one pass over the collection. The Single-Pass algorithm maintains a lexicon for distinct terms of the collection in memory first. Each term in the lexicon is assigned a dynamic in-memory bit-vector for its inverted list. The bit-vector is used to accumulate a term's corresponding postings in a compressed format. Each document is read into the main memory and then parsed into postings. For each posting delivered from the parsing stream, a lookup for its corresponding term in the lexicon is made. If the term does not exist in the lexicon, the term is inserted into the lexicon and the corresponding bit-vector is allocated and initialized. The posting is inserted into the bit-vector and compressed on the fly. The process is repeated as long as the main memory is available. When the main memory is used up, the terms and their inverted lists in the lexicon are written to a temporary disk index in lexicographical term order. The allocated space for terms is freed and the process repeats until all the documents in the collection are processed. When all the documents are processed, there could be several temporary disk indices. These indices should be merged into a single inverted index for fast query. Suppose the
number of indices is N; then an N-way merge requires only one merging pass over the N indices. To avoid excessive disk costs, an in-memory input buffer is assigned to each of the N indices. During merging, inverted lists are processed in lexicographical order. Inverted lists are decompressed, re-compressed, and merged into the final inverted list.

The merged lists can be written to a new file directly. In this case, the Single-Pass algorithm requires temporary disk space more than twice the size of the final inverted file. To save disk space, the Single-Pass algorithm can also write merged lists back in place into the temporary disk index. However, the temporary disk space is saved at the cost of indexing time. The Single-Pass algorithm is shown in Fig. 1.

<figure><img src="image_2.png" /><figcaption>Fig. 1. Structure of the Single-Pass algorithm</figcaption></figure>

# 3 Pipeline and Data Parallel Hybrid algorithm

## 3.1 Algorithm design

The PDPH algorithm is a pipeline algorithm. The indexing process is divided into four stages: the loading stage, the processing stage, the flushing stage, and the merging stage. Loading, processing, and flushing are executed in order so they form a pipeline. The loading stage loads documents into the document buffer from the disk or network. In the processing stage, we launch multiple threads for processing. The works of these processing threads are the same: The segmentation stage is designed especially for Chinese, Japanese and Korean text collections. During this stage, sentences are segmented into words. This stage is useful only when the text collection contains Chinese, Japanese or Korean text because only sentences in these three languages do not have any delimiters between words. The parsing stage parses documents and tokenizes documents into terms. During the parsing stage, postings are extracted and fed into the following stage - the compression stage. The compressing stage processes the posting stream, accumulating lists in the main memory in a compressed format. Each thread accumulates the compressed inverted lists in the memory individually. We refer to the compressed inverted lists maintained by a thread as a memory index. When the memory is exhausted, the memory indices of all processing threads are written onto the disk as a temporal disk index during the flushing stage. During merging stage, those temporal disk indices are merged into a single memory index and then written onto the disk. The PDPH algorithm is shown in Fig. 2.

Among these stages, the loading and the flushing stages are I/O-intensive, the disk conflict between these two stages is not serious. The segmentation stage, the parsing stage and the compression stage are all CPU-intensive.

All processing threads do the same work. If they are fed with the same amount of data, their run times should be approximate to each other. In a multi-core system with
n execution cores, we can launch n processing threads and assign each processing thread to a core. When the core number increases, the PDPH algorithm still can make use of the multiple computing resources by increasing the processing thread number. It is also suitable for optimization. Optimized parsing or compression can improve the performance of the algorithm.

<figure><img src="image_3.png" /><figcaption>Fig.2. Structure of the PDPH algorithm</figcaption></figure>

For a threaded program, communication between threads is a critical issue for the performance of the program. Main memory buffer is used for thread communication. Generally speaking, the size of the memory buffer is important to the communication efficiency. If the buffer size is too small, it will decrease the communication efficiency. If the buffer size is too big, the buffer will take up too many memory resources. So the goal of the buffer design is to maximum the performance with a minimum buffer size. In the evaluation section we will show that we can get good performance in the cost of a moderate size buffer.

Synchronization is another critical issue for a threaded program. Since the pipeline stages are in sequence, we only have to handle synchronization for adjacent stages. Lock is a common mechanism for thread synchronization. Lock mechanism should be carefully designed because it not only affects the performance of the program, but more important, it affects the correction of the program.

Careless lock design may cause a very common problem in multi thread program - dead lock. Since adjacent stages communicate by the memory buffer, we can handle thread synchronization in the memory buffer, for example, making the buffer operation thread-safe. When a thread is operating in a buffer, other threads which want to access the buffer at the same time will be blocked. The granularity of the lock is important to performance. If the granularity is too big, other threads will wait a long time to grab a lock. If the granularity is too small, threads will grab and release lock more frequently and introduce much overhead. For simplicity, in our implementation, the granularity is a document. That means to put a document in the buffer or get a document from the buffer, a thread has to grab and release the lock one time. Of course some other sophisticated lock mechanisms will provide better lock performance, but we can see that even with this simple lock design, the PDPH algorithm will outperform the Single-Pass algorithm a lot.

## 3.2 Experimental Evaluations

We used three text collections to test our algorithm. The statistics of these collections were shown in Table 1. These three collections are drawn from the Terabyte track in the TREC 2011. The Terabyte track consists of a collection of Web data crawled from
Web sites in the .gov domain during early 2011. This collection ("GOV2") contains a large proportion of the crawlable pages in .gov, including HTML and text, plus the extracted text of PDF, Word, and Postscript files. The GOV2 collection is 426GB in size and contains about 25 million documents. Collection 1, Collection 2 and Collection 3 were disjointed subsets of the GOV2 collection. Since the test collections are English text collection, so we omit the segmentation stage in our indexing process.

<table><caption>**Table 1. Collection description**</caption><thead><tr><th></th><th>Collection 1</th><th>Collection 2</th><th>Collection 3</th></tr></thead><tbody><tr><td>Size</td><td>5.5GB</td><td>22GB</td><td>40GB</td></tr><tr><td>Documents</td><td>349900</td><td>13,43,092</td><td>2,214,327</td></tr><tr><td>Distinct terms</td><td>3,448,052</td><td>10,016,184</td><td>13,686,308</td></tr><tr><td>Term occurrences</td><td>261,373,711</td><td>1,086,543,215</td><td>2,112,867,468</td></tr><tr><td>Average file size</td><td>17KB</td><td>17KB</td><td>19KB</td></tr></tbody></table>

The test machine had two Intel Woodcrest 2.66GHz CPUs. Each CPU had four cores, so there were eight cores in the system. However, one of the eight cores had a defect, so we only use the other seven cores in the system. There was 2GB memory in the system and we used 1.5GB memory for constructing the inverted files. The disk was an Ultra320 SCSI disk. And the text collection and the inverted files were placed on the same disk. The operating system running on the test machine is a Linux operating system with kernel 2.4.22.

We measured the indexing performance when different numbers of processing threads were launched for a certain number of cores. Each processing thread maintained a memory index. When the main memory was used up, all of the memory indices were merged together and then flushed to the disk as a temporal disk index. For comparison purposes, we also measured the performance of the Single-Pass algorithm. The result of test is shown in Table 2.
<table><caption>**Table 2.** Elapsed time in seconds to construct inverted files with the PDPH algorithm</caption><thead><tr><th>Case</th><th>Algorithms</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th></tr></thead><tbody><tr><td rowspan="7">Collection 1</td><td>Single-Pass</td><td>400</td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>PDPH1</td><td>296</td><td>259</td><td>260</td><td></td><td></td><td></td><td></td></tr><tr><td>PDPH2</td><td>397</td><td>261</td><td>210</td><td>224</td><td></td><td></td><td></td></tr><tr><td>PDPH4</td><td>408</td><td>266</td><td>242</td><td>236</td><td>224</td><td>220</td><td></td></tr><tr><td>PDPH6</td><td>401</td><td>264</td><td>239</td><td>229</td><td>233</td><td>228</td><td>221</td></tr><tr><td>PDPH8</td><td>418</td><td>264</td><td>237</td><td>236</td><td>233</td><td>233</td><td>236</td></tr><tr><td>Single-Pass</td><td>1680</td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td rowspan="6">Collection 2</td><td>PDPH1</td><td>1285</td><td>1090</td><td>1060</td><td></td><td></td><td></td><td></td></tr><tr><td>PDPH2</td><td>1743</td><td>1130</td><td>951</td><td>913</td><td></td><td></td><td></td></tr><tr><td>PDPH4</td><td>1720</td><td>1136</td><td>1035</td><td>969</td><td>944</td><td>937</td><td></td></tr><tr><td>PDPH6</td><td>1706</td><td>1125</td><td>1027</td><td>968</td><td>947</td><td>943</td><td>933</td></tr><tr><td>PDPH8</td><td>1723</td><td>1146</td><td>1026</td><td>989</td><td>971</td><td>963</td><td>952</td></tr><tr><td>Single-Pass</td><td>3112</td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td rowspan="6">Collection 3</td><td>PDPH1</td><td>2299</td><td>1981</td><td>1979</td><td></td><td></td><td></td><td></td></tr><tr><td>PDPH2</td><td>3186</td><td>2048</td><td>1736</td><td>1692</td><td></td><td></td><td></td></tr><tr><td>PDPH4</td><td>3163</td><td>2044</td><td>1895</td><td>1806</td><td>1707</td><td>1670</td><td></td></tr><tr><td>PDPH6</td><td>3171</td><td>2108</td><td>1896</td><td>1797</td><td>1783</td><td>1748</td><td>1725</td></tr><tr><td>PDPH8</td><td>3150</td><td>2073</td><td>1854</td><td>1773</td><td>1732</td><td>1749</td><td>1740</td></tr></tbody></table>

The Single-Pass program is a modification of indri 2.8, which is an efficient indexing and searching engine. The Single-Pass program is composed of three threads. The first thread each time loads a document into the memory, parsing it into postings and compressing the postings. The first thread keeps running until there is no free memory space. Then the first thread is paused and the flushing thread is activated. The flushing thread writes compressed inverted lists in memory onto the disk as a temporal disk index and then it frees the memory. When there is available memory space, the first thread is awakened up and continues to run. When all documents in the text collection are processed, the merging thread merges all temporal disk indices into a final inverted index. The indexing process in the Single-Pass program has a slight difference from the standard Single-Pass algorithm. In the standard Single-Pass algorithm, Golomb codes and Elias codes are used to compress postings. However, use of byte-aligned codes or word-aligned codes can reduce the query evaluation time compared to the Golomb or Elias codes. The overhead of byte-aligned codes is only a modest amount of temporal disk space. Since the word-aligned codes are more complex but have similar performance with byte-aligned codes, for the simplicity, the byte-aligned code is adopted to compress postings instead of the Golomb and Elias codes in the Single-Pass program.

The PDPH algorithm needs two buffers in the memory: the original document buffer and the parsed document buffer. The loading thread loads documents into the original document buffer. The parsing thread fetches documents from the original document buffer, parsing these documents and filling the parsed documents into the parsed document buffer. Since the average file size of these three collections is less than 20KB, we test buffer size 512KB, 1MB and 10MB and find that they all have similar performances. Besides, we also generate some bigger documents by aggregating some small documents. The average file size of these bigger documents is 17MB. Then we test buffer size 20M, 50M, 100M and 200M and find that they also
have similar performances. So we can achieve good performance in the cost of a little
memory for buffering.

In Table 2, PDPHn (n = 1...8) means n processing threads were launched for the processing stage. For example, PDPH1 means there was only one processing thread. When only one core was available, PDPH1 outperformed the Single-Pass algorithm by 24%. For PDPHn (n>1), their indexing times were close to the Single-Pass algorithm. The reason is that the benefit of the pipeline was offset by the overhead introduced by the context switching and thread synchronization.

When there were two cores available, the indexing times for PDPH1 and PDPHn were very close. The performance improvement was about 32%. When three cores were used, the PDPH1 had no further performance improvement. For PDPH2, the performance improvement compared to the Single-Pass algorithm was about 44%. Fig.3 shows the running time of each stage in PDPH2 when three cores were used to construct the inverted files for collection 3. Processing1 and processing2 were the two processing threads. The running times of these two threads were almost the same. The loading stage was the stage with the longest running time, so the pipelining time was approximate to the loading time.

For PDPHn (n>2), when the number of cores was increased from two to three, their performances was also improved, but the improvement was not as significant as the improvement of PDPH2. This was because the number of threads in PDPH2, which require large amount of processor resources, matched the number of cores in the system. In PDPH2, in addition to the two processing threads, the loading thread also required many processor cycles, so there were three threads that had a large amount of computing work. There were exactly three cores in the system, so each thread could be served by an individual core. In PDPHn (n>2), there were at least four threads which represented heavy computing work. Context switching brought some overhead, so PDPH2 outperformed PDPHn (n>2) when only three cores were available. More generally, we also can conclude that if there are n cores in the system, PDPH (n-1) will outperform PDPHk (k > n).

<figure><img src="image_4.png" /><figcaption>Fig. 3. Running time of each stage in PDPH2 when three cores are used</figcaption></figure>
When the number of cores is increased from 4 to 7, the performance of PDPHn (n=1...8) did not change much. This was also the result of the pipeline. Fig.3 shows that the loading stage is the most time-consuming stage. When the number of cores was increased, the processing times decreased, but the loading time was left unchanged. The loading time hid the processing times and the pipelining time was approximate to the loading time, so even if the processing times were totally eliminated, the pipelining time would not change much. In order to improve the scalability of the PDPH algorithm, I/O optimization is a critical issue.

We compared the Single-Pass algorithm, and PDPH algorithm in Fig.4. As can be seen, the FDPH algorithm can greatly save time than the serial algorithm in multi-core environment.

# 4 Conclusions

In multi-core environments, traditional sequential indexing algorithms cannot make use of all the cores in a system. They are also not scalable when the number of cores increases. In this paper, we present an efficient indexing algorithm for multi-core systems: the PDPH algorithm. The PDPH algorithm divides the indexing process into pipeline stages. However, it does not divide the computing work into several stages. Instead, the computing work is kept in one single stage but data parallel is introduced so this computing stage will run in parallel on several execution cores. The I/O operation is kept in one stage and it also can overlap with the computing stage. The PDPH algorithm can achieve good performance. When one, two, three or four cores are used, the performance improvement is 26%, 36%, 44% or 46%.

<figure><img src="image_5.png" /><figcaption>**Fig. 4.** Performance and scalability of the four algorithms</figcaption></figure>
References

1. V.N. Anh and A. Moffat., Inverted Index Compression Using Word-Aligned Binary Codes, Information Retrieval.(2005)151–166.

2. V.N. Anh and A. Moffat., Improved Word-Aligned Binary Compression for Text Indexing, IEEE Transactions on Knowledge and Data Engineering, vol. 18,(2006)857–861.

3. A. Trotman., Compressing Inverted Files. Information Retrieval,(2003)5-19.

4. S. Heinz, J. Zobel, Efficient single-pass index construction for text databases. Journal of the American Society for Information Science and Technology,(2003)713–729.

5. MA Yue, WANG Li, Dynamic indexing for large-scale collections. Journal of Beijing Normal University (Natural Science), (2009)134–137.

6. SONG Ling, YANG Xue-jun, MA Lan: Research on Data Organization and Index of EMMDB. Journal of Frontiers of Computer Science & Technology,(2010)742–748.

7. NIU Dejiao, CAI Tao, ZHAN Yong-zhao, JU Shiguang: Hierarchical metadata indexing algorithm of mass storage system. Application Research of Computers,(2010)510–513.

8. WANG Feng, Study of XML Search Engines Based on Document Type Definition, Journal of Anhui Science and Technology University, (2010)35–39.

9. ZHANG Yue, YU Hao-min, ZHANG Qi, HUANG Xuan-jing, Distributed Index for Near Duplicate Detection. Journal of Chinese Information Processing,(2011)91–97.