An OpenMP static scheduling method for random cycle load balancing

By designing a Dual_static scheduling strategy in OpenMP, and utilizing pre-running to obtain load information and calculate the iterative block index, the problem of random cyclic load imbalance is solved, achieving efficient load balancing without scheduling overhead and improving program execution efficiency.

CN115344367BActive Publication Date: 2026-04-14ZHEJIANG GONGSHANG UNIVERSITY
View PDF 2 Cites 0 Cited by

Patent Information

Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
ZHEJIANG GONGSHANG UNIVERSITY
Filing Date
2022-08-12
Publication Date
2026-04-14

AI Technical Summary

Technical Problem

Existing OpenMP scheduling strategies struggle to simultaneously meet the requirements of load balancing and low scheduling overhead when dealing with random loops. Static scheduling leads to load imbalance, while dynamic and guided scheduling introduce additional scheduling overhead.

Method used

By obtaining load information from the loop iterations through pre-running, a static scheduling strategy is adopted to redistribute the random loop tasks. The Dual_static scheduling method is designed to calculate the start and end indices of the iteration block for each thread in order to achieve load balancing.

Benefits of technology

It achieves load balancing without scheduling overhead in a multi-threaded environment, improving program execution efficiency and achieving an average speedup of 8% compared to existing strategies.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN115344367B_ABST
    Figure CN115344367B_ABST
Patent Text Reader

Abstract

The application discloses an OpenMP static scheduling method for random loop load balancing. After the configuration of OMPi compiler in the linux environment, the random loop part in the calculation program is isolated. Then the execution time in each loop iteration is obtained by using the idea of iterative compilation, and the execution time is used to represent the load contained in the random loop. Then according to the obtained load information and the actual running thread number required, the load of each iteration in the random loop, the total load and the average load are obtained, the start and end indexes of each thread distribution to the iteration block are calculated, and the start and end index values are respectively stored in the corresponding pointers. Finally, the code about OpenMP scheduling in the compiler is changed to realize the scheduling strategy. The application overcomes the shortcoming of additional time overhead caused by pre-running, has no scheduling overhead, realizes the load balancing and speeds up the execution efficiency of the program.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This invention relates to the field of OpenMP static scheduling for load balancing in multi-threaded environments, and specifically to a static scheduling method based on iterative compilation for random loops. Background Technology

[0002] OpenMP is a shared-memory multithreaded parallel programming model based on compiler directives. Due to its simplicity and efficiency, it is supported by mainstream compilers such as GCC, ICC, and LLVM, and is currently the primary means of thread-level parallel programming. OpenMP provides three standard scheduling strategies for random loop parallelization: static scheduling, dynamic scheduling, and guided scheduling. However, for some specific random loop patterns, existing standard scheduling strategies struggle to simultaneously meet the requirements of good load balancing and low scheduling overhead. Existing standard scheduling strategies have several shortcomings in handling random loops. For example, dynamic scheduling and its variants: The most common approach for handling random loops is to use dynamic scheduling, which balances the load among threads by continuously requesting fixed-size iteration blocks; adaptive scheduling, which establishes a task queue, with each thread taking iteration blocks from the queue, retrieving them after each task is completed, until the queue is empty; and task stealing, where a thread, after completing its tasks, transitions to an idle state and steals some tasks from busy threads, thus remaining busy until all tasks are completed. Static scheduling, which evenly distributes the load across iterations, results in significant differences in workload between different threads, slowing down overall execution efficiency. Guided scheduling, with its increasingly smaller iteration blocks, concentrates the load in the early and middle threads, leading to an unbalanced workload.

[0003] The core idea of ​​the scheduling methods described above is not complex. It typically involves an initial partitioning based on the number of threads, followed by dynamic allocation of the remaining load during program execution. Load balancing is achieved through frequent iteration block allocation. In terms of effectiveness, the scheduling methods mentioned above handle load well when dealing with large programs. However, they introduce new operations (fetching iteration blocks, task queues, task stealing), resulting in some scheduling overhead. Essentially, they trade scheduling overhead for load balancing. Summary of the Invention

[0004] To address the issue of high scheduling overhead when using dynamic scheduling strategies for random loops, this invention proposes an OpenMP static scheduling method (Dual_static) for load balancing in random loops. By obtaining load information from loop iterations through pre-running, tasks in the random loop are reallocated, and a scheduling strategy that satisfies load balancing in random loops is designed.

[0005] This invention mainly includes the following steps:

[0006] Step 1: Configure the OMPi compiler in the Linux environment.

[0007] Step 2: Use code isolation to isolate the random loop portion of the calculation program. Add the `volatile` keyword before key variables to prevent the compiler from automatically optimizing and identifying the random loop as dead code.

[0008] Step 3: Using iterative compilation, a tick count timing function is inserted inside the random loop to obtain the execution time within each loop iteration. This execution time is then used to characterize the load contained in the random loop. To reduce the cost of obtaining load information, static scheduling is used for multi-threaded execution during the pre-running of the random loop to record load information. This scheduling strategy automatically obtains the number of cores on the target platform and uses the maximum number of cores as the number of threads for static scheduling. After the loop completes execution, the time information, i.e., the load information, is output.

[0009] Step 4: Calculate the average load based on the obtained load information and the actual number of threads required for execution, i.e., avg_load = load / p. Divide the random loop iteration block into p blocks, each containing a load equal to the average load avg_load. Calculate the load time(i), total load load, and average load avg_load for each iteration in the random loop.

[0010] Step 5: Based on the load time(i), total load, and average load avg_load of each iteration obtained in Step 4, calculate the start index start(i) and end index end(i) of the iteration block assigned to each thread.

[0011] Step 6: Based on start(i) and end(i) obtained in Step 5, store the start iteration index and end iteration index of the iteration block in pointers *fiter and *liter respectively, and implement the code for the Dual_static scheduling strategy.

[0012] Step 7: Modify the OpenMP scheduling code in the OMPi compiler to implement the scheduling strategy of this invention. The C code (foo.c) containing OpenMP directives is converted into intermediate language form (foo.pc) by the preprocessor. The intermediate language code is further processed by the OMPi compiler, primarily by calling the OMPi compiler conversion function to convert the random loop containing OpenMP directives into C code based on thread libraries such as pthreads (foo_ompi.c). Finally, the user-specified C compiler is called to compile it into executable code based on the runtime library.

[0013] Step 8: After compilation, the original serial program will be compiled into a multithreaded program based on the pthreads thread library. The random loops that need to run in parallel will be defined as parallel regions in OpenMP. Within the parallel region, the random loop iterations will be divided into several parts according to the scheduling policy and then allocated to all threads within the parallel region. When a thread reaches the end of the parallel region, it will stop executing and wait for all threads to finish before performing data synchronization.

[0014] The beneficial effects of this invention are as follows: This invention overcomes the disadvantage of additional time overhead caused by pre-running by using code isolation. Based on the obtained load distribution information, the start index and end index of the iteration block under the average load are calculated, and then imported into the OMPi compiler scheduling function to uniformly divide the random cyclic load. There is no scheduling overhead, and load balancing is achieved, which speeds up the execution efficiency of the program. Attached Figure Description

[0015] Figure 1 Before random cyclic iteration block partitioning;

[0016] Figure 2 After partitioning into random cyclic iterative blocks;

[0017] Figure 3 MS load distribution;

[0018] Figure 4 This represents the effect of parallel execution of MS. Detailed Implementation

[0019] To make the objectives, technical solutions, and advantages of this invention clearer, the invention will be further described in detail below with reference to the accompanying drawings.

[0020] An OpenMP static scheduling strategy for random cyclic load balancing mainly includes the following steps:

[0021] Step 1: Configure the OMPi compiler in the Linux environment. Table 1 is a guide to configuring and using the OMPi compiler.

[0022] Table 1

[0023]

[0024] Step 2 involves isolating the random loop portion of the computation program using code isolation. The other parts of the program are not executed during iterative compilation, simplifying the program into a lightweight program containing only the random loop. Only the necessary data needs to be provided for the random loop to execute. To prevent the compiler from automatically optimizing the random loop as dead code after code isolation, the `volatile` keyword is added before critical variables.

[0025] Step 3: Use the OpenMP function `omp_get_max_threads()` to obtain the target platform's core count, and add the OpenMP compiler directive `#pragma omp parallel for num_threads(H)` above the random loop, where `H` is the obtained target platform core count. Using iterative compilation, insert a tick count timing function inside the random loop to obtain the execution time within each loop iteration, and use the execution time to characterize the load contained in the random loop. To reduce the cost of obtaining load information, static scheduling is used for multi-threaded execution during the loop pre-run to record load information. This scheduling strategy uses the maximum number of cores as the number of statically scheduled threads, and outputs the time information, i.e., the load information, after the loop completes execution.

[0026] Step 4: Calculate the average load based on the acquired load information and the actual number of threads required for execution, i.e., avg_load = load / p. Divide the loop iteration block into p blocks, each containing a load equal to the average load avg_load. The resulting static scheduling strategy is load-balanced and has no scheduling overhead during runtime. The specific execution process is as follows:

[0027]

[0028] Where A is a random loop, p is the number of threads started, niters is the total number of iterations of the loop, time(i) is the execution time of the i-th iteration, start(i) is the starting index of thread i assigned to the iteration block, end(i) is the ending index of thread i assigned to the iteration block, load is the total load of the loop, and avg_load is the average load.

[0029] Through the above process, we obtain the load time(i), total load, and average load avg_load for each iteration in the random loop.

[0030] Step 5: Based on the load time(i), total load, and average load avg_load of each iteration obtained in Step 4, calculate the start index start(i) and end index end(i) of the iteration block assigned to each thread. Figure 1 For the Dual_static scheduling policy, the load information acquisition phase, where t0~t niters Corresponding to time(i), Figure 2 The random loop is divided into consecutive iterative blocks according to the average load.

[0031] In step 4, the cyclic iteration is divided into p blocks based on the random cyclic load information. It is also necessary to ensure that the load contained in each block is equal to the average load, i.e., t. (start) +t (start+1) +t (start+2) ...+t (end) ≈avg_load, where t (start) ~t (end) This corresponds to the execution time of each iteration block within a given thread, i.e., the load of each iteration block within the thread. The specific methods for calculating the start and end indices of a thread's iteration blocks are as follows:

[0032]

[0033]

[0034] Based on the load time(i), total load, and average load avg_load obtained in step 4 for each iteration, the load of each thread is checked against the load accumulation condition of each iteration block in the thread to determine whether the load of each thread has reached the average load avg_load. When the accumulated load of each iteration block in the thread exceeds the average load avg_load, the difference between the previous accumulated value and avg_load and the difference between the current accumulated value and avg_load are calculated. The two differences are compared, and the smaller difference determines the thread's end index, ensuring further improvement in load balancing and preventing a sudden increase or decrease in the load of a certain loop iteration from affecting the partitioning.

[0035] Step 6: Based on the start(i) and end(i) obtained in Step 5, store the start and end iteration indices of the iteration block in pointers *fiter and *liter respectively, and implement the Dual_static scheduling strategy. The pseudocode is as follows:

[0036]

[0037] Step 7: Modify the OpenMP scheduling code in the OMPi compiler to implement the scheduling strategy of this invention. The C code (foo.c) containing OpenMP directives is converted into intermediate language form (foo.pc) by the preprocessor. The intermediate language code is further processed by the OMPi compiler, primarily by calling the OMPi compiler conversion function to convert the random loop containing OpenMP directives into C code based on thread libraries such as pthreads (foo_ompi.c). Finally, the user-specified C compiler is called to compile it into executable code based on the runtime library.

[0038] The target platform selected in this embodiment is an Intel Xeon Platinum 9242 CPU, which uses a shared memory architecture where all cores share 191GB of RAM via a 100Gb Intel ominipath interconnect. In addition, for the purposes of this embodiment, the environment is also equipped with an FFTW library for performing Fast Fourier Transform, and a C++ Boost library to improve program performance. Specific hardware and software environment parameters are shown in Table 2.

[0039] Table 2 Hardware and software environment parameters

[0040]

[0041] Step 8: After compilation, the original serial program will be compiled into a multithreaded program based on the pthreads thread library. The random loops that need to run in parallel will be defined as parallel regions in OpenMP. Within the parallel region, loop iterations will be divided into several parts according to the scheduling policy and then allocated to all threads within the parallel region. When a thread reaches the end of the parallel region, it will stop executing and wait for all threads to finish before performing data synchronization.

[0042] The classic Mandelbrot Set (MS) program was used for testing. The MS program employs a randomized loop structure to compute the Mandelbrot set in the complex plane. To fully verify the performance of the test cases, the selected experiments were conducted as many times as possible, ensuring that the acceleration effect came from the scheduling strategy rather than random factors, thus eliminating random factors and verifying the reliability and scalability of the scheduling strategy. For timing operations, the OpenMP timing function `omp_get_wtime()` was used, which returns a double-precision floating-point value equal to the elapsed clock time (in seconds). Figure 3 This demonstrates the trend of MS load changing with iteration.

[0043] For the MS program, the test cases first tested the serial execution time of the program as a baseline, which was 750 seconds. Based on this, to verify the effectiveness of the Dual_static scheduling strategy, the execution times of dynamic scheduling, static scheduling, and guided scheduling were first tested with 6, 12, 24, and 48 threads respectively as a comparative experiment. Then, under the same conditions, the execution time of the Dual_static scheduling strategy was tested. The experimental results were compared to verify the effectiveness of the scheduling strategy in this embodiment, and the results are shown in Table 3.

[0044] Table 3 MS Parallel Execution Time (s)

[0045]

[0046] The Mandelbrot Set (MS) is a randomized cyclic structure whose loop contains a load such as... Figure 3 As shown, the load initially increases and then decreases. In this situation, it's clear that static scheduling and guided scheduling cannot balance the load. Static scheduling evenly distributes the load across iterations, while guided scheduling distributes the load as the number of iterations within each allocated iteration block decreases. Ultimately, static scheduling concentrates the load on the middle threads, while guided scheduling concentrates the load on the early and middle threads. Dynamic scheduling, because it can dynamically balance the load, outperforms both static and guided scheduling, with the Dual_static scheduling strategy performing best. This is because the load in the Dual_static scheduling strategy is strictly balanced with the partitioning of iteration blocks, and this strategy is based on static scheduling, thus incurring no scheduling overhead compared to dynamic scheduling. Figure 4 This is a graph showing the effect of the MS program under different scheduling strategies, which can more intuitively show the experimental results. The pure gray fill represents the Dual_static scheduling strategy.

[0047] This invention uses classic random loop test cases to test the proposed scheduling strategy; the results show that the Dual_static scheduling strategy achieves an average speedup of 8% compared to the three existing scheduling strategies of OpenMP when handling random loop structures, under various thread counts.

Claims

1. An OpenMP static scheduling method for random cyclic load balancing, characterized in that... It mainly includes the following steps Step 1: Configure the OMPi compiler in a Linux environment; Step 2: Use code isolation to isolate the random loop part in the calculation program and add the volatile keyword before the key variables; Step 3: Using the idea of ​​iterative compilation, insert a tick count timing function inside the random loop to obtain the execution time within each loop iteration, and use the execution time to characterize the load contained in the random loop; When recording load information during random loop pre-run, a multi-threaded execution method is adopted using static scheduling. The number of cores of the target platform is automatically obtained, and the maximum number of cores is used as the number of threads for static scheduling. After the loop execution is completed, the time information, i.e. the load information, is output. Step 4: Calculate the average load based on the obtained load information and the actual number of running threads, i.e., avg_load = load / p. Divide the loop iteration block into p blocks, and the load contained in each block is equal to the average load avg_load. Calculate the load time(i), total load, and average load avg_load for each iteration of the random loop; Step 5: Based on the load time(i), total load, and average load avg_load of each iteration obtained in Step 4, calculate the start index start(i) and end index end(i) of the iteration block assigned to each thread. Step 6: Based on start(i) and end(i) obtained in step 5, store the start iteration index and end iteration index of the iteration block in pointers *fiter and *liter, respectively; Step 7: Modify the OpenMP scheduling code in the OMPi compiler to implement the scheduling strategy; Step 8: After compilation by the compiler, the original serial program will be compiled into a multi-threaded program based on the pthreads thread library. The parallel random loops in the program are defined as parallel regions in OpenMP. In the parallel region, the loop iteration is divided into several parts according to the scheduling policy, and then distributed to all threads in the parallel region; When a thread reaches the end of the parallel section, it stops executing and waits for all threads to finish before performing data synchronization.

2. The OpenMP static scheduling method for random cyclic load balancing according to claim 1, characterized in that: In step 2, other parts of the program are not executed during iterative compilation, simplifying the program into a lightweight program containing only random loops, providing only the necessary data for the execution of the random loops.

3. The OpenMP static scheduling method for random cyclic load balancing according to claim 1, characterized in that: Step 3 also includes using the OpenMP function omp_get_max_threads() to obtain the number of cores on the target platform, and adding the OpenMP compiler directive "#pragma omp parallel for num_threads(H)" above the random loop, where H is the number of cores on the target platform obtained.

4. The OpenMP static scheduling method for random cyclic load balancing according to claim 1, characterized in that: The changes to the OpenMP scheduling code in the OMPi compiler mentioned in step 7 are as follows: The C code foo.c, which contains OpenMP guidance statements, is converted into intermediate language form foo.pc by a preprocessor. The intermediate language code will be further processed by the OMPi compiler, mainly by calling the OMPi compiler conversion function to convert the random loop with OpenMP guidance statements into C code foo_ompi.c based on thread libraries such as pthreads; Continue by calling the user-specified C compiler to compile it into executable code based on the runtime library.

Citation Information

Patent Citations

  • Multi-core platform oriented multithreaded division and static balancing scheduling policy

    CN105700959A

  • Performing power management in a multicore processor

    CN107209545A