An Optimization Method for Flash Sort Algorithm for GPU and DCU Architectures
Patent Information
- Application Number
- CN202310653455.2
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2023-06-02
- Publication Date
- 2026-09-01
- Estimated Expiration
- 2043-06-02
AI Technical Summary
[0006]本发明的目的在于解决现有Flash sort算法所存在的资源占用率低,总体性能不高的问题,将Flash sort算法在GPU和DCU架构上实现并优化,充分利用GPU、DCU高度并行的优点,提高Flash sort排序算法的运行速度
[0017]This invention can process array A (an array to be sorted) at different levels (device/block/wavefront). The number of buckets is set according to the numerical range of elements in the array to be sorted, and the storage address of the array is re-divided according to the number of elements in each bucket, storing the elements into their corresponding buckets. Threads are divided into several thread groups, each group working together to sort the elements in one bucket. Each thread is responsible for sorting multiple elements within a bucket, and storage space is pre-allocated on the LDS. More specifically:
Smart Images

Figure CN116680073B_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of high-performance computing and algorithm technology, specifically to a Flash Sort algorithm optimization method for GPU and DCU architectures. Background Technology
[0002] In computer science and mathematics, sorting algorithms can arrange a set of data according to a specific sorting method. Commonly used sorting algorithms include bubble sort, insertion sort, merge sort, odd-even sort, and so on.
[0003] Graphics Processing Units (GPUs) and Deep Computing Units (DCUs) offer powerful parallel computing capabilities and massive data throughput, excelling in handling large-scale numerical computation problems and providing a robust computing platform for high-performance computing systems. Based on the parallel computing capabilities of GPUs and DCUs, algorithms can sort multiple datasets simultaneously, significantly improving the running speed of sorting algorithms.
[0004] The Flash sort algorithm adds guessing of data distribution to bucket sort, reducing the number of buckets used. However, existing Flash sort algorithms are not well optimized for GPU and DCU architectures, resulting in low resource utilization and failing to fully utilize the performance of GPU and DCU accelerators. Therefore, this invention proposes an optimized Flash sort algorithm method for GPU and DCU architectures.
[0005] This invention provides an optimization method for the Flash sort algorithm, which implements and optimizes the Flash sort algorithm on GPU and DCU architecture, making full use of the advantages of high parallelism of GPU and DCU, and improving the running speed of the Flash sort algorithm. Summary of the Invention
[0006] The purpose of this invention is to solve the problems of low resource consumption and low overall performance of the existing Flash sort algorithm. The Flash sort algorithm is implemented and optimized on GPU and DCU architecture, making full use of the advantages of high parallelism of GPU and DCU to improve the running speed of Flash sort algorithm.
[0007] To achieve the above objectives, the present invention adopts the following technical solution:
[0008] An optimization method for Flash Sort algorithm for GPU and DCU architectures includes the following steps:
[0009] S1. Initialization: Based on the size of array A, different levels of calculation are used, such as device / block / wavefront, and the parameters are set, including the number of elements processed by each thread and the number of buckets.
[0010] S2. Calculate bucket ID: Each thread processes multiple elements, calculates the bucket ID to which each element belongs, and calculates the number of each element within the bucket, storing it in LDS (shared memory); at the same time, it calculates the number of elements in each bucket and stores it in the array bucket_size;
[0011] S3. Calculate the prefix sum: Calculate the prefix sum of the array bucket_size, and redistribute the storage space according to the size of the buckets to determine the starting position of each bucket in the array;
[0012] S4. Put array elements into buckets: Rewrite the elements in the array into the storage space and put them into the specified bucket space according to the storage space divided in S3.
[0013] S5. Bucket Sort: Divide the thread into several thread groups, each thread group processes one bucket sort. Each thread calculates the position of the element in the bucket and stores it in the thread's temporary array; add the position in the bucket to the starting position of the bucket to get the position of the element in the array.
[0014] S6. Write back the final result: After all elements have calculated their positions, each thread writes the result stored in the temporary array back to the storage space.
[0015] Preferably, S1 specifically includes the following: at the device level, multiple blocks jointly process array A; at the block level, one block processes array A; at the wavefront level, one wavefront processes array A; the number of buckets is set according to the number of elements in the array, and a fixed-size space is allocated on the LDS to store the array elements.
[0016] Compared with existing technologies, this invention provides a Flash Sort algorithm optimization method for GPU and DCU architectures, which has the following advantages:
[0017] This invention can process array A (an array to be sorted) at different levels (device / block / wavefront). The number of buckets is set according to the numerical range of elements in the array to be sorted, and the storage address of the array is re-divided according to the number of elements in each bucket, storing the elements into their corresponding buckets. Threads are divided into several thread groups, each group working together to sort the elements in one bucket. Each thread is responsible for sorting multiple elements within a bucket, and storage space is pre-allocated on the LDS. More specifically:
[0018] (1) This invention effectively utilizes the parallel computing capabilities of GPU and DCU: it optimizes the flashsort sorting algorithm for GPU and DCU architecture, in which all threads participate in the calculation and the data is evenly distributed to each thread according to the amount of data. In the worst case, only some threads in one round will be idle, which improves the utilization rate of computing resources and can effectively improve the running efficiency of the flashsort sorting algorithm.
[0019] (2) The present invention can perform adaptive parameter setting: according to the number of elements and the value range of the array A to be sorted, the various parameters of the sorting algorithm are adaptively adjusted to speed up the sorting speed of the array and improve the running efficiency.
[0020] (3) This invention effectively utilizes LDS shared memory: improving data access efficiency, reducing inter-thread communication, and eliminating the need to allocate additional LDS space when putting data into buckets while maintaining parallelism. It also avoids large-scale data copying operations, simply reusing the allocated space. This improves the running efficiency of the Flash sort algorithm. Attached Figure Description
[0021] Figure 1 This is a flowchart of a Flash Sort algorithm optimization method for GPU and DCU architectures proposed in this invention.
[0022] Figure 2 This is a logical schematic diagram of a Flash Sort algorithm optimization method for GPU and DCU architectures proposed in this invention. Detailed Implementation
[0023] The technical solutions of the present invention will be clearly and completely described below with reference to the accompanying drawings of the embodiments of the present invention. Obviously, the described embodiments are only some embodiments of the present invention, and not all embodiments.
[0024] Please see Figure 1 This invention proposes an optimization method for the Flash Sort algorithm for GPU and DCU architectures, specifically including the following:
[0025] Before sorting, calculations are performed at different levels (device, block, and wavefront) based on the size of array A, with parameters set, including the number of elements processed by each thread and the number of buckets. At the device level, multiple blocks process array A together; at the block level, one block processes array A; and at the wavefront level, one wavefront processes array A. Each thread calculates the bucket IDs of multiple elements and obtains the element's position within the bucket and the total number of elements in the bucket through atomic addition operations. A prefix sum operation is performed on the number of elements in each bucket to obtain the starting and ending indices of each bucket in the array, determining the position of each bucket in the array. The elements in the array are rewritten into the array according to their bucket IDs, with each element stored in the array position corresponding to its bucket. The threads are divided into several thread groups, each processing one bucket and performing sorting operations on the data within the bucket. Each thread calculates the sorting index of multiple elements within the bucket and adds it to the starting index of the bucket to obtain the element's index in the array. After completing the index calculation, the elements are written back into the array.
[0026] Please see Figure 2 , combined Figure 2 The sorting operation for array A is explained below:
[0027] Assuming the array length is 9 and the number of buckets is 3, the thread first calculates the bucket ID to which each element belongs. Taking the first element as an example, its value is 1, then... Bucket 0 occupies the position [0, 4) in the array, so the first element is placed in bucket 0. After all elements are placed in buckets, each thread group sorts the elements within a single bucket to obtain the element's index within the bucket. At this point, the index of the first element in bucket 0 is 1. Adding the bucket index to the bucket's starting index gives the index of the second element in the array after sorting: 0 + 1 = 1. After obtaining the array index, the data is written to the corresponding position. The following further illustrates the Flash Sort algorithm optimization method for GPU and DCU architectures proposed in this invention with specific examples.
[0028] Example 1:
[0029] Taking array A as an example (A = a) i ∈F n Array A has a length of n and the i-th element is a. i This invention optimizes the Flashsort algorithm at the device, block, and wavefront levels. The specific details are as follows:
[0030] Device level:
[0031] (1) Initialization: When array A is large, multiple blocks work together to sort A, each block handles sorting within a bucket independently, and each thread processes multiple elements. The number of buckets is defined as bucket_num. Array A is stored in video memory.
[0032] (2) Calculate the bucket ID: Traverse array A, obtain the maximum and minimum values of array A. Each block traverses a portion of array A, storing the maximum and minimum values in video memory. After all blocks have completed their calculations, a single block reads the results of traversing each block to obtain the maximum and minimum values of array A. Within each block, the thread calculates the bucket number (bucket_id) to which the corresponding element belongs. Among them, a i It is the value of the element to be processed, a min Let a be the minimum value in array A. max The maximum value in array A is given. The block creates LDS shared memory arrays block_count and block_bucket_size. When calculating bucket_id, it also records the element's bucket number block_bucket_inner_id and stores it in array block_count. It calculates the number of elements in each bucket and stores it in array block_bucket_size. The length of block_bucket_size is bucket_num.
[0033] (3) Calculate the prefix sum. Calculate the prefix sum of each block's `block_bucket_size` column-wise. For each block, read the calculated `block_bucket_size` and merge them into `scan_block_bucket_size`. The size of the `scan_block_bucket_size` array is [block_num, block_bucket_size], and its i-th row is the calculation result of the i-th block. Each block calculates the prefix sum of one column of `scan_block_bucket_size`. A total of j rounds of calculation are performed when calculating the prefix sum of a block, where j = [log2(block_num, block_bucket_size]]. num )], where block num The number of threads within the block; in each round, thread k obtains the (k-2)th thread. jThe data of thread number 1 is added to the data of the current thread to obtain the prefix sum of the current column, and the result is written back to scan_block_bucket_size. Each block rereads the i-th row of data of scan_block_bucket_size and updates the block_bucket_inner_id inside each block according to the result to ensure that the number of each element in the bucket is unique and that address conflicts will not occur during writing. Then, a single block sums the block_bucket_size of each block column by column to obtain the number of internal elements of each bucket in the entire array range, globel_bucket_size. Then, a single block is called to calculate the prefix sum of globel_bucket_size, and the calculation method is the same as the above method. The storage space of array A is re-divided according to the prefix sum result to obtain the starting index and ending index of each bucket in the storage space. Bucket number 0 occupies the position of array A storage space [0, globel_bucket_size[0]), and bucket number i (i>0) occupies the position of array A storage space [globel_bucket_size[i-1], globel_bucket_size[i]).
[0034] (4) Rewrite the data in each block back into the original array. Each thread in the block processes N elements, copies the N elements and their bucket numbers to a local temporary array, and then puts the elements into the specified bucket according to the bucket number and the bucket number, overwriting the original data.
[0035] (5) In-bucket sorting. Each block processes the internal sorting of a bucket. Each thread processes a single element at a time, comparing the single element with the size of other elements in the bucket to obtain the element's index within the bucket. The bucket index is then added to the bucket's starting index based on `globel_bucket_size` to obtain the element's position in the array. Each thread records the processed element and its array position in a temporary array.
[0036] (6) Write back the final result. After all threads have finished calculating, each thread will rewrite the elements stored in the temporary array into the array based on the array positions calculated in the previous step.
[0037] Block level:
[0038] (1) Initialization: A block processes array A, each thread processes N elements, and the number of buckets (bucket_num) is defined. An LDS array is created to store array A. An LDS array (count) is created to store the sorted order of elements in array A.
[0039] (2) Calculating the bucket ID: Threads within the block process array A together, traversing array A. Each thread reads multiple data points from array A and compares them to obtain the maximum and minimum values, storing these values in shared memory. Simultaneously, the threads within the block calculate the bucket number to which each element in the array belongs. Among them, a i It is the value of the element to be processed, a min Let a be the minimum value in array A. max This represents the maximum value in array A. While calculating `bucket_id`, the element's bucket ID (`bucket_inner_id`) is also recorded and stored in the array `count`. The number of elements within each bucket is calculated and stored in the LDS array `bucket_size`, where `bucket_size` has a length of `bucket_num`.
[0040] (3) Calculate the prefix sum: Perform a prefix sum operation on the bucket_size array. The prefix sum is calculated in j rounds within the block, where j = [log2(block...]. num In each round, thread k obtains the (k-2)th... j The data from thread number 1 is added to the data from the current thread, and the result is written back to `bucket_size`. If `bucket_num` is less than `wavefront_size` (where `wavefront_size` is the number of threads within a wavefront), the prefix sum operation is performed within a single wavefront. The storage space of array A is re-divided according to `bucket_size`. Bucket number 0 occupies the storage space of array A at position [0, bucket_size[0]), and bucket number i (i>0) occupies the storage space of array A at position [bucket_size[i-1], bucket_size[i]). `bucket_size` internally stores the start and end indices of each bucket.
[0041] (4) Rewrite the data in array A back into the original array: Each thread in the block processes N elements, copies the N elements and the bucket number to the local temporary array, and then puts the elements into the specified bucket, overwriting the original data.
[0042] (5) Bucket Sorting: The threads within the block are divided into several thread groups, each containing a power of 2 threads. Each thread group is called a vector. Each vector processes the internal sorting of a bucket independently. Each thread processes a single element at a time, comparing the single element with the size of other elements in the bucket to obtain the element's index within the bucket. The bucket index is added to the bucket's starting index based on the bucket_size to obtain the element's position in the array. Each thread records the element and its array position in a temporary array.
[0043] (6) Write back the final result: After all threads have finished calculating, each thread will write back the elements stored in the temporary array into the array according to the array position calculated in the previous step.
[0044] Wavefront level:
[0045] (1) Initialization: When the array length is small and there are multiple arrays that need to be sorted, define a wavefront to process array A, with each thread processing N elements, and define the number of buckets, bucket_num. Create an LDS array to store array A. Create an LDS array count to store the sorted element order of array A.
[0046] (2) Calculating the bucket ID: Threads within Wavefront work together on thread A, traversing array A. Each thread reads multiple data points from array A and compares them to obtain the maximum and minimum values, storing these values in shared memory. Simultaneously, the threads within Wavefront calculate the bucket ID (bucket_id) to which each element in the array belongs. Among them, a i It is the value of the element to be processed, a min Let a be the minimum value in array A. max This represents the maximum value in array A. While calculating `bucket_id`, the element's bucket ID (`bucket_inner_id`) is also recorded and stored in the array `count`. The number of elements within each bucket is calculated and stored in the LDS array `bucket_size`, where `bucket_size` has a length of `bucket_num`.
[0047] (3) Calculate the prefix sum: Perform a prefix sum operation on the bucket_size array. The prefix sum is calculated in j rounds during wavefront, where j = [log2(block...]. num In each round, thread k obtains the (k-2)th... jThe data from thread i is added to the data from the current thread, and the result is written back to `bucket_size`. The storage space of array A is re-divided according to `bucket_size`. Bucket 0 occupies the storage space of array A at position [0, bucket_size[0]), and bucket i (i>0) occupies the storage space of array A at position [bucket_size[i-1], bucket_size[i]). `bucket_size` internally stores the start and end indices of each bucket.
[0048] (4) Rewrite the data in array A back into the original array: Each thread in wavefront processes N elements, copies the N elements and the bucket number to a local temporary array, and then puts the elements into the specified bucket, overwriting the original data.
[0049] (5) Bucket Sorting: The threads within Wavefront are divided into several groups, each containing a power of 2 threads. Each thread group is called a vector. Each vector processes the internal sorting of a bucket independently. Each thread processes a single element at a time, comparing the single element with the size of other elements in the bucket to obtain the element's index within the bucket. The bucket index is added to the bucket's starting index based on the bucket_size to obtain the element's position in the array. Each thread records the element and its array position in a temporary array.
[0050] (6) Write back the final result: After all threads have finished calculating, each thread will write back the elements stored in the temporary array into the array according to the array position calculated in the previous step.
[0051] The above description is only a preferred embodiment of the present invention, but the scope of protection of the present invention is not limited thereto. Any equivalent substitutions or modifications made by those skilled in the art within the scope of the technology disclosed in the present invention, based on the technical solution and inventive concept of the present invention, should be covered within the scope of protection of the present invention.
Claims
1. A Flash Sort algorithm optimization method for GPU and DCU architectures, characterized in that, Includes the following steps: S1. Initialization: Based on the size of array A, different levels of calculation are used, such as device / block / wavefront, and the parameters are set, including the number of elements processed by each thread and the number of buckets. S2. Calculate bucket ID: Each thread processes multiple elements, calculates the bucket ID to which each element belongs, and calculates the number of each element within the bucket, storing them in shared memory; at the same time, it calculates the number of elements in each bucket and stores them in the array bucket_size; S3. Calculate the prefix sum: Calculate the prefix sum of the array bucket_size, and redistribute the storage space according to the size of the buckets to determine the starting position of each bucket in the array; S4. Put array elements into buckets: Rewrite the elements in the array into the storage space and put them into the specified bucket space according to the storage space divided in S3. S5. Bucket Sort: Divide the thread into several thread groups, each thread group processes one bucket sort. Each thread calculates the position of the element in multiple buckets and stores it in the thread's temporary array. Add the position in the bucket to the starting position of the bucket to get the position of the element in the array. S6. Write back the final result: After all elements have calculated their positions, each thread writes the result stored in the temporary array back to the storage space.
2. The Flash Sort algorithm optimization method for GPU and DCU architectures according to claim 1, characterized in that, S1 specifically includes the following: At the device level, multiple blocks work together to process array A; at the block level, one block processes array A; at the wavefront level, one wavefront processes array A; the number of buckets is set according to the number of elements in the array, and a fixed-size space is allocated on the LDS to store the array elements.
Citation Information
Patent Citations
GPU (graphics processing unit) sorting-based MapReduce optimizing method
CN106802787A
Methods and apparatus for data-parallel execution of operations on segmented arrays
WO2015099562A1