A method, apparatus and device for acquiring a lock resource
Patent Information
- Application Number
- CN202111227144.7
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2021-10-21
- Publication Date
- 2026-10-23
- Estimated Expiration
- 2041-10-21
Smart Images

Figure CN116010040B_ABST
Abstract
Description
Technical Field
[0001] This application relates to the field of computer technology, and in particular to a method, apparatus, and device for acquiring lock resources. Background Technology
[0002] A mutex is a commonly used synchronization primitive. It is used to provide mutual exclusion guarantees for multithreaded applications. When multiple threads need to modify shared data (such as the same entry in a database), these threads need to compete to acquire the mutex; at any given time, only the thread that acquires the mutex can modify the shared data. If a thread acquires a mutex, other threads competing for the mutex must enter a sleep state.
[0003] Currently, there are other methods for acquiring mutex locks.
[0004] For example, if a mutex is acquired by one thread, other threads competing for the mutex will not go to sleep but will continuously check whether the mutex has been released; and only after the mutex is released will they compete for it again. A mutex acquired in this way is also called a spin lock.
[0005] However, during the loop detection process, a number of new threads may be added. After the spinlock is released, these new threads compete for the spinlock with the threads that were previously looping to check whether the spinlock has been released, resulting in unfairness between the new threads and the threads that were previously looping to check whether the spinlock has been released.
[0006] To ensure fairness in the competition for a mutex lock among multiple threads, queue locks were introduced. Queue locks maintain a first-in, first-out waiting queue. Each thread that wants to acquire the mutex lock must first join the waiting queue, and the threads that join the waiting queue first acquire the mutex lock first.
[0007] Taking the Asymmetric Multiprocessor (AMP) as an example, a heterogeneous multiprocessor can also be called an asymmetric multiprocessor. It contains multiple cores of different sizes. Large cores usually refer to cores with better performance, while small cores usually refer to cores with poorer performance.
[0008] If a thread running on a small core needs to acquire a mutex, it must be added to the waiting queue. Subsequently, if a thread running on a large core needs to acquire a mutex, it must also be added to the waiting queue. Since the thread running on the small core is added to the waiting queue before the thread running on the large core, the thread running on the small core acquires the mutex first.
[0009] However, due to the poor performance of small cores, threads running on small cores take a long time to execute critical sections (code sections protected by mutexes) after acquiring mutexes. This results in longer waiting times for threads running on large cores, leading to a decrease in processor throughput. Summary of the Invention
[0010] This application provides a method, apparatus, and device for acquiring lock resources. The method enables a second thread running on a high-priority second core to be added to a waiting queue before a first thread running on a low-priority first core, thereby allowing the second thread to acquire lock resources first, reducing the waiting time of the second thread and improving the processor's throughput.
[0011] In a first aspect, embodiments of this application provide a method for acquiring lock resources, applied to a computer device. The processor of the computer device includes a first core and a second core, with the first core and the second core corresponding to different priorities. Based on this, the method includes: running a first code segment by a first thread running on the first core to perform the following first operation, wherein the first code segment refers to a piece of code in an application: determining that the priority of the first core is lower than the priority of the second core. There are various methods for determining this, such as setting different priority identifiers for the first core and the second core, with the first core corresponding to a low-priority identifier and the second core corresponding to a high-priority identifier. In this way, the first thread can determine that the priority of the first core is lower than the priority of the second core based on the priority identifier corresponding to the first core; delaying the addition to the waiting queue when the waiting queue is not empty, so that the second thread running on the second core joins the waiting queue before the first thread. The waiting queue is used to compete for lock resources. Embodiments of this application do not specifically limit the duration of the delay.
[0012] Since the first core has a lower priority than the second core, if the waiting queue is not empty, the first thread running on the first core will be added to the waiting queue later, so that the second thread running on the second core can be added to the waiting queue before the first thread. In this way, the second thread can acquire the lock resource first and thus can execute the critical section first.
[0013] Therefore, the method for acquiring lock resources according to the embodiments of this application allows threads running on high-priority cores to execute critical sections before threads running on low-priority cores, thereby reducing the waiting time of threads running on high-priority cores and increasing the number of times threads running on high-priority cores execute critical sections. Furthermore, since high-priority cores are usually high-performance cores, threads running on high-performance cores execute critical sections for shorter periods, while threads running on low-performance cores execute critical sections for longer periods. Therefore, increasing the number of times threads running on high-priority cores execute critical sections can increase the total number of critical section executions within a fixed time period, thereby improving throughput.
[0014] As one possible approach, determining that the priority of the first core is lower than that of the second core includes: determining that the priority of the first core is lower than that of the second core based on the fact that the performance of the second core is better than that of the first core. Here, the performance of the core can be determined by multiple parameters, such as frequency, cache, etc.
[0015] Since the performance of the second core is better than that of the first core, the embodiments of this application can reduce the waiting time of threads running under the high-performance core and increase the number of times the threads running under the high-performance core execute the critical section. Furthermore, since the execution time of the critical section of the threads running under the relatively high-performance core is shorter, while the execution time of the critical section of the threads running under the relatively low-performance core is longer, the total number of times the critical section is executed can be increased within a fixed time period, thereby improving the throughput.
[0016] As an feasible approach, when the waiting queue is not empty, delayed joining of the waiting queue includes: when the waiting queue is not empty, the first thread enters a backoff state, which is a state of waiting to join the waiting queue; and joins the waiting queue based on the duration of entering the backoff state being greater than or equal to the out-of-order duration.
[0017] Because the first thread is added to the waiting queue when the waiting time is greater than or equal to the out-of-order duration, the waiting time of the first thread is prevented from being too long, which would affect the normal operation of the first code segment.
[0018] As one possible approach, before adding to the waiting queue, the first operation also includes: obtaining the out-of-order duration. There are multiple methods for determining the out-of-order duration, and this application embodiment does not specifically limit this. For example, the out-of-order duration can be obtained based on whether there is a delay requirement in the first code segment.
[0019] After determining that the first core has a lower priority than the second core, the out-of-order duration is obtained, and the waiting time of the first thread is controlled by the out-of-order duration to prevent the waiting time of the first thread from being too long and affecting the normal operation of the first code segment.
[0020] As one possible approach, after determining that the priority of the first core is lower than that of the second core, the out-of-order duration is obtained based on the duration of entering the backoff state being greater than or equal to the out-of-order duration.
[0021] As an achievable method, obtaining the out-of-order duration includes: based on the existence of a latency requirement in the first code segment, obtaining the first duration corresponding to the first code segment as the out-of-order duration. The first duration is obtained based on the latency requirement. There are multiple methods to determine the first duration based on the latency requirement. For example, the first duration can be estimated based on the target latency specified by the latency requirement, and then the first duration can be adjusted later. The first duration is usually less than the target latency.
[0022] Since the first code segment has a latency requirement, the first duration is determined based on the latency requirement, and the first duration is used as the out-of-order duration. This can prevent the first code segment from running for too long due to an excessively long out-of-order duration, thus failing to meet the latency requirement.
[0023] As one possible approach, the method further includes: before running the first code segment, performing the following second operation through the first thread: setting the value of a global variable to the first identifier of the first code segment, where the global variable represents the code segment with latency requirements; before obtaining the first duration corresponding to the first code segment as the out-of-order duration based on the existence of latency requirements in the first code segment, the first operation further includes: determining that the first code segment has latency requirements based on the value of the global variable to the first identifier.
[0024] In this implementation, a global variable is introduced to mark the first code segment with latency requirements. Before running the first code segment, the value of the global variable is set to the first identifier of the first code segment, so that the first thread can determine that the first code segment has latency requirements based on the value of the global variable. The method of marking the first code segment with a global variable is simple and easy to implement.
[0025] As one possible approach, the method also includes: after running the first code segment, performing the following third operation through the first thread: setting the value of the global variable to a second identifier, where the second identifier does not identify any code segment.
[0026] Since the first thread can execute multiple code segments, failing to set the value of the global variable to the second identifier may lead to incorrect calculation of out-of-order durations. For example, if the next code segment after the first code segment does not have a latency requirement, and the global variable is not set to the second identifier, its value will still be the first identifier. Thus, during the execution of the next code segment by the first thread, the first duration corresponding to the first code segment will be incorrectly used as the out-of-order duration. Therefore, setting the value of the global variable to the second identifier can prevent errors in calculating out-of-order durations.
[0027] As one possible approach, the method further includes: after running the first code segment, performing the following third operation through the first thread: obtaining the actual running duration of the first code segment. Specifically, when running the first code segment, the timestamp of starting to run the first code segment can be recorded. When the first code segment finishes running, the timestamp of finishing running the first code segment can be obtained. Based on the timestamp of starting to run the first code segment and the timestamp of finishing running the first code segment, the actual running duration of the first code segment can be calculated. Based on the relative size between the actual running duration and the target latency specified by the latency requirement, the first duration is adjusted. There can be multiple methods to adjust the first duration.
[0028] Since the first duration is obtained based on the latency requirement, but the first duration may not be accurate enough, for example, if the first duration is too short, the actual running time of the first code segment will be much shorter than the latency requirement, or if the first duration is too long, the actual running time of the first code segment will be much longer than the latency requirement. Therefore, the first duration is adjusted based on the relative size between the actual running time of the first code segment and the target latency specified by the latency requirement, so as to meet the latency requirement of the first code segment while achieving the delayed addition of the first thread.
[0029] As an feasible approach, adjusting the first duration based on the relative magnitude between the actual running time and the target latency includes: shortening the first duration if the actual running time is greater than the target latency, wherein the amount of shortening can be adjusted according to actual needs.
[0030] Since the actual running time is greater than the target latency, shortening the first duration can make the actual running time of the first code segment less than the target latency, thereby meeting the latency requirements of the first code segment while achieving the delayed addition of the first thread.
[0031] As an achievable approach, adjusting the first duration based on the relative magnitude between the actual running time and the target latency includes: extending the first duration if the actual running time is less than the target latency.
[0032] Since the actual running time is less than the target latency, the first duration is extended. This extends the duration of the first thread in the backoff state as much as possible while meeting the latency requirements of the first code segment, so that the second thread can be added to the waiting queue first, thereby improving throughput.
[0033] As one feasible approach, obtaining the out-of-order duration includes: based on the fact that there is no latency requirement in the first code segment, obtaining the second duration as the out-of-order duration.
[0034] Since the first code segment does not have a delay requirement, the second duration is usually longer; obtaining the second duration as the out-of-order duration allows the first thread to be able to join the waiting queue with a delay.
[0035] As one feasible approach, after determining that the first code segment has no latency requirement and using a fixed second duration as the out-of-order duration, the first operation further includes: determining that the first code segment has no latency requirement based on the value of a global variable being a second identifier. The global variable represents the code segment with latency requirements, and the second identifier does not identify any code segment. The fact that the second identifier does not identify any code segment can also be understood as meaning that there is currently no code segment with latency requirements.
[0036] In this implementation, a global variable is introduced to mark the first code segment with latency requirements. In this way, the value of the global variable can be used as a second identifier to determine that the first code segment does not have latency requirements. This method of marking the first code segment with a global variable is simple and easy to implement.
[0037] As an feasible approach, when the waiting queue is not empty, delayed joining of the waiting queue also includes: detecting the waiting queue based on the fact that the duration of entering the backoff state is less than the out-of-order duration; and joining the waiting queue when it is empty.
[0038] Since the time to enter the backoff state is less than the out-of-order time, the waiting queue is checked, and if the waiting queue is empty, the thread is added to the waiting queue. This can prevent the first thread from being in the backoff state when the waiting queue is empty, thereby maximizing the use of lock resources and improving throughput.
[0039] As one possible approach, after determining that the first core has a lower priority than the second core, the first operation also includes: adding the core to the waiting queue if the waiting queue is empty.
[0040] Adding a thread to the waiting queue when it is empty can prevent the first thread from being in a backoff state even when the waiting queue is empty, thereby maximizing the use of lock resources and improving throughput.
[0041] Secondly, embodiments of this application provide an apparatus for acquiring lock resources, applied to a computer device. The processor of the computer device includes a first core and a second core. The apparatus includes: a determining unit, used to determine that the priority of the first core is lower than the priority of the second core; and a queue joining unit, used to delay joining the waiting queue when the waiting queue is not empty, so that a second thread running under the second core joins the waiting queue before the first thread, and the waiting queue is used to compete for lock resources.
[0042] As one possible approach, a unit is determined to prioritize the first core over the second core based on the fact that the performance of the second core is superior to that of the first core.
[0043] As one possible approach, a queue addition unit is used to allow the first thread to enter a backoff state when the waiting queue is not empty. The backoff state is a state of waiting to be added to the waiting queue. The thread is added to the waiting queue based on the duration of the backoff state being greater than or equal to the out-of-order duration.
[0044] As one possible approach, queue addition units are used to obtain out-of-order duration.
[0045] As one possible approach, a queue addition unit is used to obtain the first duration corresponding to the first code segment as the out-of-order duration based on the latency requirement of the first code segment. The first duration is obtained based on the latency requirement.
[0046] As one possible implementation, the device further includes: a first setting unit, used to set the value of a global variable to a first identifier of a first code segment, wherein the global variable represents a code segment with latency requirements; and a queue joining unit, used to determine that the first code segment has latency requirements based on the value of the global variable being the first identifier.
[0047] As one possible implementation, the device also includes a second setting unit for setting the value of a global variable to a second identifier, wherein the second identifier does not identify any code segment.
[0048] As one possible approach, the apparatus further includes: an adjustment unit for obtaining the actual running duration of the first code segment; and adjusting the first duration based on the relative magnitude between the actual running duration and the target delay specified by the delay requirement.
[0049] As one possible approach, the adjustment unit is used to shorten the first duration based on the actual running time being greater than the target latency.
[0050] As one possible approach, the adjustment unit is used to extend the first duration based on the actual running time being less than the target delay.
[0051] As one possible approach, a queue-added unit is used to obtain a second duration as the out-of-order duration based on the fact that there is no delay requirement in the first code segment.
[0052] As one possible approach, a queue is added to a unit, which is used to determine whether the first code segment has no latency requirement based on the value of a global variable as a second identifier. The global variable represents the code segment with latency requirement, while the second identifier does not identify any code segment.
[0053] As one possible approach, a queue addition unit is used to detect the waiting queue based on the fact that the duration of entering the backoff state is less than the out-of-order duration; if the waiting queue is empty, the queue is added.
[0054] As one possible approach, a queue addition unit is used to add a member to the waiting queue when the waiting queue is empty.
[0055] For details on the implementation, related explanations, and technical effects of each of the above units, please refer to the description of the first aspect of the embodiments of this application.
[0056] A third aspect of this application provides a computer device, the computer device including a memory and a processor, the memory being used to store computer-readable instructions (or computer programs), and the processor being used to read the computer-readable instructions to implement the method provided in any of the foregoing implementations.
[0057] A fourth aspect of this application provides a computer program product containing instructions, characterized in that, when run on a computer, it causes the computer to perform the method as described in any of the foregoing aspects and various possible implementations.
[0058] A fifth aspect of this application provides a computer-readable storage medium including instructions, characterized in that, when the instructions are executed on a computer, the computer performs the method as described in any one of the first aspects and various possible implementations above.
[0059] A sixth aspect of this application provides a chip including one or more processors. Part or all of the processors are configured to read and execute a computer program stored in a memory to perform the methods in any possible implementation of the first aspect described above.
[0060] Optionally, the chip includes a memory, which is connected to the processor via a circuit or wire. Further optionally, the chip also includes a communication interface, to which the processor is connected. The communication interface is used to receive data and / or information that needs to be processed. The processor obtains the data and / or information from the communication interface, processes the data and / or information, and outputs the processing result through the communication interface. The communication interface can be an input / output interface.
[0061] In some implementations, some of the processors may implement some steps of the above method through dedicated hardware. For example, the processing of neural network models may be implemented by a dedicated neural network processor or graphics processor.
[0062] The method provided in this application embodiment can be implemented by a single chip or by multiple chips working together. Attached Figure Description
[0063] Figure 1 A core schematic diagram of the computer device provided in the embodiments of this application;
[0064] Figure 2 This is a schematic diagram of a first embodiment of a method for acquiring lock resources provided in this application.
[0065] Figure 3 This is a schematic diagram of a second embodiment of a method for acquiring lock resources provided in this application.
[0066] Figure 4 This is a flowchart illustrating one embodiment of obtaining the out-of-order duration in this application.
[0067] Figure 5 A schematic diagram of a third embodiment of a method for acquiring lock resources provided in the application embodiments;
[0068] Figure 6 This is a flowchart illustrating another embodiment of obtaining the out-of-order duration in this application.
[0069] Figure 7 This describes the process of adding the first thread to the waiting queue in the embodiments of this application;
[0070] Figure 8 This is a schematic diagram illustrating the addition of an out-of-order lock to an application in an embodiment of this application;
[0071] Figure 9 This is a schematic diagram illustrating the first thread being added to the waiting queue in an embodiment of this application.
[0072] Figure 10 This is a diagram comparing the throughput of the target library with the throughput of other locks.
[0073] Figure 11 This is a schematic diagram illustrating the change in epoch latency in the embodiments of this application;
[0074] Figure 12 A schematic diagram of a device for acquiring lock resources is also provided as an embodiment of this application;
[0075] Figure 13 This is a schematic diagram of the structure of a computer device provided in an embodiment of this application. Detailed Implementation
[0076] The embodiments of this application are described below with reference to the accompanying drawings. Obviously, the described embodiments are only a part of the embodiments of this application, and not all of them. As those skilled in the art will recognize, with the development of technology and the emergence of new scenarios, the technical solutions provided by the embodiments of this application are also applicable to similar technical problems.
[0077] The terms "first," "second," etc., used in the specification, claims, and accompanying drawings of this application are used to distinguish similar objects and are not necessarily used to describe a specific order or sequence. It should be understood that such data can be interchanged where appropriate so that the embodiments described herein can be implemented in a sequence other than that illustrated or described herein. Furthermore, the terms "comprising" and "having," and any variations thereof, are intended to cover non-exclusive inclusion; for example, a process, method, system, product, or device that includes a series of steps or modules is not necessarily limited to those explicitly listed, but may include other steps or modules not explicitly listed or inherent to such processes, methods, products, or devices. The naming or numbering of steps appearing in this application does not imply that the steps in the method flow must be performed in the chronological / logical order indicated by the naming or numbering. The execution order of named or numbered process steps can be changed according to the desired technical purpose, as long as the same or similar technical effect is achieved.
[0078] Furthermore, in the description of this invention, unless otherwise stated, "multiple" means two or more. The term "and / or" or the character " / " in this application is merely a description of the relationship between related objects, indicating that three relationships can exist. For example, A and / or B, or A / B, can represent: A existing alone, A and B existing simultaneously, and B existing alone.
[0079] The embodiments of this application can be applied to Figure 1The computer device shown contains a processor that includes multiple cores of different sizes. It should be noted that the size of a core is a relative size; a large core may be a core with superior performance, while a small core may refer to a core with inferior performance.
[0080] Specifically, Figure 1 It shows 4 cores, which include 1 core A, 2 cores B and 1 core C.
[0081] exist Figure 1 In the diagram, the size of the circle represents the size of the core; based on Figure 1 It can be seen that core A is greater than core B, which can be specifically manifested in the fact that the performance of core A is better than that of core B; core B is greater than core C, which can be specifically manifested in the fact that the performance of core B is better than that of the smaller core C.
[0082] Compared to Figure 1 For the core A in the middle, Figure 1 Core B in the middle can be regarded as a small core; relative to Figure 1 For the core B in the middle, Figure 1 The core C in the code can also be considered a small core.
[0083] Understandably, when multiple threads need to modify shared data, they all need to compete to acquire the lock that protects the shared data.
[0084] There are various types of locks, such as spin locks and queue locks.
[0085] However, spin locks can lead to unfairness between threads, while queue locks, although they can guarantee fairness between threads, can also lead to a decrease in throughput.
[0086] The following is based on Figure 1 This will be illustrated using core A and core B as examples.
[0087] Suppose that a lock is held by a certain thread. In the period before the lock is released, threads 1, 2, 3, 4, 5 and 6 request the lock in chronological order. Threads 1 and 3 run in kernel B, while threads 2, 4, 5 and 6 run in kernel A.
[0088] If the lock being held is a spin lock, then regardless of the order in which the lock is requested, after the lock is released, threads 1, 2, 3, 4, 5, and 6 will simultaneously compete for the lock through atomic operations. Specifically, threads 1, 2, 3, 4, 5, and 6 will set the lock variable to a characteristic value (e.g., 1). If one of the threads successfully sets the lock variable, that thread will acquire the spin lock. Here, atomic operations refer to operations that will not be interrupted by the thread scheduling mechanism.
[0089] Since core A performs better than core B, the probability of threads 2, 4, 5, and 6 successfully executing atomic operations is greater than that of threads 1 and 3. Therefore, the probability of threads 2, 4, 5, and 6 successfully competing for a spinlock is greater than that of threads 1 and 3.
[0090] The final result of the lock contention was that threads 2, 4, 5, 6 and 1 acquired the spin lock in turn, while thread 3 did not acquire the spin lock due to time constraints.
[0091] If the lock being held is a queue lock, since the order in which the lock is requested is thread 1, thread 2, thread 3, thread 4, thread 5, and thread 6, the order in which the lock is added to the waiting queue is also thread 1, thread 2, thread 3, thread 4, thread 5, and thread 6.
[0092] It should be noted that after a thread acquires a lock, it needs to execute the critical section (the code section protected by the lock) to modify the shared data, and only the thread that acquires the queue lock can enter the critical section.
[0093] Because of the poor performance of core B, threads 1 and 3 spend a long time executing the critical section after competing for the queue lock. Since time is limited, the final result of the lock competition is: threads 1, 2, 3, and 4 acquire the queue lock in sequence, while threads 5 and 6 do not acquire the queue lock within this limited time.
[0094] Based on the above explanation, within the same time period, if the lock held is a queue lock, 4 threads will each execute the critical section once through the queue lock; while if the lock held is a spin lock, 5 threads will each execute the critical section once through the spin lock. Therefore, the number of times the critical section is executed through the queue lock is less than the number of times the critical section is executed through the spin lock. That is, the queue lock will lead to a decrease in throughput, where throughput can be understood as the amount of service provided per unit time.
[0095] The queue lock mentioned above can also be called a FIFO Ticket Spinlock, or simply a FIFO lock. A FIFO lock can be understood as a new type of spin lock.
[0096] To address this, this application provides a method for acquiring lock resources. This method utilizes existing FIFO locks, but before adding a thread to the waiting queue, it first determines the priority of the core of the running thread. When the core priority is low, the thread is added to the waiting queue with a delay. In this way, before the thread is added to the waiting queue, the thread running under the high-priority core can be added to the waiting queue first. Therefore, even if the thread running under the high-priority core requests the lock resource later than the thread running under the low-priority core, it can still acquire the lock resource first. Here, the lock resource can also be simply referred to as a lock.
[0097] Therefore, the embodiments of this application can reduce the time for threads running under high-priority cores to acquire lock resources. When a high-priority core is a high-performance core, it means that threads running under a high-priority core can acquire lock resources first and execute critical sections. Since threads running under high-priority cores execute critical sections for a shorter time, the number of times critical sections are executed within a certain period of time can be increased, thereby improving throughput.
[0098] It should be noted that, in the embodiments of this application, even if a thread running on a high-priority core competes for the lock resource later than a thread running on a low-priority core, it can still join the waiting queue and acquire the lock resource earlier than a thread running on a low-priority core. Therefore, the lock in the embodiments of this application can be regarded as a new type of FIFO lock; the embodiments of this application refer to this new type of FIFO lock as a reorderable lock.
[0099] The methods provided in the embodiments of this application will be described in detail below.
[0100] like Figure 2 As shown, this application provides a first embodiment of a method for acquiring lock resources. This first embodiment is applied to a computer device whose processor includes multiple cores. This application does not limit the specific number of cores; for example, the number of cores can be 2, 3, or more than 3.
[0101] Multiple cores correspond to multiple priorities, and there are various methods for dividing priorities. This application does not specifically limit the methods for dividing priorities. Generally, multiple cores can be prioritized based on their performance.
[0102] by Figure 1 Taking the four cores in the image as an example, these four cores can be divided into three priorities based on their performance. Specifically, core A corresponds to the first priority, core B corresponds to the second priority, and core C corresponds to the third priority.
[0103] The four cores can also be divided into two priorities based on their performance. Specifically, core A corresponds to the first priority, while cores B and C both correspond to the second priority; or cores A and B correspond to the first priority, while core C corresponds to the second priority.
[0104] Typically, multiple cores can be divided into two priorities.
[0105] For ease of explanation, the following description uses the first and second cores among multiple cores as examples to illustrate the method provided in the embodiments of this application.
[0106] Specifically, the methods include:
[0107] The first code segment is executed by running the first thread on the first core to perform the first operation. The first code segment refers to a piece of code in the application that can be used to process a certain request.
[0108] It should be noted that multiple code segments can be executed through the first thread, and the first code segment can be any one of the multiple code segments.
[0109] The first operation includes:
[0110] Step 101: Determine that the priority of the first core is lower than that of the second core.
[0111] As can be seen from the foregoing description, the priority of the cores is usually based on the performance of the cores. Accordingly, step 101 may include: determining that the priority of the first core is lower than that of the second core based on the fact that the performance of the second core is better than that of the first core.
[0112] Specifically, the first core and the second core can be assigned corresponding priorities in advance, and different priority identifiers can be set for the first core and the second core based on their different priorities. In this way, the first thread can determine that the priority of the first core is lower than that of the second core based on the priority identifier corresponding to the first core.
[0113] For example, the priority identifier of the first core is AA, and the priority identifier of the second core is BB. The priority represented by AA is lower than the priority represented by BB. When the first thread determines that the priority of the first core is AA instead of BB, it can determine that the priority of the first core is lower than the priority of the second core.
[0114] Step 102: If the waiting queue is not empty, delay adding to the waiting queue so that the second thread running under the second core can join the waiting queue before the first thread. The waiting queue is used to compete for lock resources.
[0115] Delayed joining of the waiting queue can be understood as not immediately joining the waiting queue when it is certain that the waiting queue is not empty, but waiting for a period of time before joining the waiting queue; during this waiting period, the second thread can join the waiting queue first.
[0116] It should be noted that there are multiple methods for delaying joining the queue, and this application embodiment does not specifically limit this method. The following will describe it in detail.
[0117] Since the waiting queue has been explained above, it will not be elaborated on here; in short, the thread that joins the waiting queue first will acquire the lock resource first.
[0118] Step 103: If the waiting queue is empty, add it to the waiting queue.
[0119] It is understandable that if the waiting queue is empty, not adding to the waiting queue will waste lock resources and also lead to a decrease in throughput; therefore, step 103 can improve throughput.
[0120] It should be noted that when multiple cores correspond to two priorities, if the priority of the first core is determined to be higher, it can be directly added to the waiting queue regardless of whether the waiting queue is empty.
[0121] In this embodiment, since the priority of the first core is lower than that of the second core, the first thread running on the first core is delayed in joining the waiting queue when the waiting queue is not empty, so that the second thread running on the second core can join the waiting queue before the first thread; in this way, the second thread can acquire the lock resource first, and thus can execute the critical section first.
[0122] Based on this, the method provided in the embodiments of this application acquires lock resources so that threads running on high-priority cores can execute critical sections before threads running on low-priority cores, thereby reducing the waiting time of threads running on high-priority cores and increasing the number of times threads running on high-priority cores execute critical sections. Since high-priority cores are usually high-performance cores, threads running on high-performance cores execute critical sections for a shorter time, while threads running on low-performance cores execute critical sections for a longer time. Therefore, increasing the number of times threads running on high-priority cores execute critical sections can increase the total number of critical section executions within a fixed time period, thereby improving throughput.
[0123] Based on the relevant explanation in step 102 above, if the waiting queue is not empty, the user is added to the waiting queue after a delay, and the length of the delay can be set according to actual needs.
[0124] For example, developers may have latency requirements for the execution of certain code segments. Based on this, different delay times are set for the two cases: the first code segment has latency requirements and the first code segment does not have latency requirements.
[0125] The method provided in this application embodiment will be described below under two scenarios: when the first code segment has a latency requirement and when the first code segment does not have a latency requirement.
[0126] Here, we will first introduce the scenario where the first code segment has latency requirements, such as... Figure 3 As shown, this application provides a second embodiment of a method for acquiring lock resources, which includes:
[0127] Step 201: Set the value of the global variable to the first identifier of the first code segment.
[0128] Global variables represent code segments that have latency requirements.
[0129] To facilitate the determination that the first code segment has a latency requirement, this embodiment introduces a global variable; when the value of the global variable is the first identifier of the first code segment, it indicates that the first code segment has a latency requirement.
[0130] As explained above, multiple code segments can be run through the first thread. In order to accurately identify the code segments with latency requirements, each code segment corresponds to a globally unique identifier, so the first identifier is also globally unique.
[0131] Before executing step 201, the initial value of the global variable can be set. This initial value usually does not identify any code segment. The specific value of the initial value can be set according to actual needs. For example, the initial value can be -1, and this initial value will also be referred to as the second identifier below.
[0132] It should be noted that there are multiple ways to determine that the first code segment has a delay requirement, and introducing a global variable is just one of them, so step 201 is optional.
[0133] In this embodiment, step 201 can be executed before the first code segment is run; the operation performed before the first code segment is called the second operation, and step 201 is included in the second operation.
[0134] After performing the second operation, the first code segment is run through the first thread to perform the first operation (i.e., steps 202 to 207). At the same time, the timestamp of the start of the first code segment is recorded, which is used to calculate the actual running time of the first code segment.
[0135] Step 202: Determine that the priority of the first core is lower than that of the second core.
[0136] Step 202 is similar to step 101. For details, please refer to the relevant explanation of step 101 to understand step 202.
[0137] Step 203: Obtain the out-of-order duration.
[0138] Out-of-order duration refers to the time during which the first thread and the second thread are allowed to join the waiting queue out of order; that is, the time during which the first thread is delayed in joining the queue, or the time during which the first thread waits to join the queue.
[0139] Based on the foregoing description, the out-of-order duration can be determined based on whether there is a delay requirement for the first code segment, and in this embodiment, the first code segment has a delay requirement.
[0140] Therefore, as a feasible approach, such as Figure 4 As shown, step 203 includes:
[0141] Step 301: Determine that the first code segment has a latency requirement.
[0142] There are multiple methods to determine that the first code segment has a latency requirement, and this application does not specifically limit the methods.
[0143] If step 201 is performed, step 301 may include:
[0144] The value of the global variable is the first identifier, which determines that there is a delay requirement in the first code segment.
[0145] Step 302: Based on the latency requirement of the first code segment, obtain the first duration corresponding to the first code segment as the out-of-order duration. The first duration is obtained based on the latency requirement.
[0146] There are various methods for determining the first duration based on latency requirements, and this application does not limit the specific methods used in the embodiments.
[0147] For example, the first duration can be estimated based on the target latency specified by the latency requirement, and then the first duration can be adjusted later.
[0148] It should be noted that out-of-order duration refers to the time it takes for the first thread to wait to be added to the queue. In addition, it also takes time for the first thread to execute other parts of the code in the first code segment. Therefore, the first duration is usually less than the target latency required by the latency requirement.
[0149] In this embodiment, the first duration can be dynamically adjusted.
[0150] Step 203 is executed before step 205. This application embodiment does not specifically limit the order of steps 203 and 204. Specifically, step 203 can be executed first and then step 204 can be executed, or step 204 can be executed first and then step 203 can be executed.
[0151] Step 204: If the waiting queue is not empty, the first thread enters the backoff state, which is the state of waiting to be added to the waiting queue.
[0152] In the backoff state, the first thread does not join the waiting queue.
[0153] Understandably, in order to calculate the duration of the first thread entering the backoff state, the timestamp of entering the backoff state can be recorded when it enters the backoff state.
[0154] Step 205: Add to the waiting queue if the duration of entering the backoff state is greater than or equal to the out-of-order duration.
[0155] Understandably, before executing step 205, it is necessary to calculate the duration of entering the backoff state. Specifically, the current time can be continuously obtained, and the duration of entering the backoff state can be calculated based on the current time and the timestamp of entering the backoff state. If the duration of entering the backoff state is greater than or equal to the out-of-order duration, it is added to the waiting queue.
[0156] If the duration of entering the backoff state is less than the out-of-order duration, repeat the above operation, that is, obtain the current time again and recalculate the duration of entering the backoff state until the duration of entering the backoff state is greater than or equal to the out-of-order duration.
[0157] Step 206: Based on the fact that the duration of entering the backoff state is less than the out-of-order duration, detect the waiting queue.
[0158] It should be noted that if the duration of entering the backoff state is less than the out-of-order duration, in addition to recalculating the duration of entering the backoff state, the waiting queue can also be checked to avoid a situation where the duration of entering the backoff state is less than the out-of-order duration but the waiting queue is empty; in this case, if the first thread is still in the backoff state, it will result in a waste of lock resources.
[0159] It is not necessary to check the waiting queue every time the duration of entering the backoff state is calculated. In other words, the number of times the waiting queue is checked can be less than the number of times the duration of entering the backoff state is calculated, thereby avoiding additional latency caused by frequent checks.
[0160] Specifically, an exponential backoff check strategy can be used to detect waiting queues. That is, when the number of times the duration of entering the backoff state is calculated is an exponential multiple and the duration of entering the backoff state is less than the out-of-order duration, the waiting queue is detected; while when the number of times the duration of entering the backoff state is calculated is not an exponential multiple, the waiting queue is not detected.
[0161] For example, after the first calculation of the duration of entering the backoff state, if the duration of entering the backoff state is less than the out-of-order duration, the waiting queue is checked; after the second calculation of the duration of entering the backoff state, if the duration of entering the backoff state is less than the out-of-order duration, the waiting queue is checked; after the fourth calculation of the duration of entering the backoff state, if the duration of entering the backoff state is less than the out-of-order duration, the waiting queue is checked; after the eighth calculation of the duration of entering the backoff state, if the duration of entering the backoff state is less than the out-of-order duration, the waiting queue is checked; and so on.
[0162] When the number of times the duration of entering the backoff state is calculated is a non-exponential multiple, such as the 3rd, 5th, or 6th time, the waiting queue is not checked.
[0163] Step 207: If the waiting queue is empty, add the item to the waiting queue.
[0164] By executing step 207, it is possible to prevent the first thread from being in a backoff state when the waiting queue is empty, thereby maximizing the use of lock resources and improving throughput.
[0165] It should be noted that steps 203 to 207 constitute the specific implementation plan of step 102.
[0166] After the first operation is performed through the first thread, the third operation (i.e., steps 208 to 210) can also be performed through the first thread.
[0167] Step 208: Set the value of the global variable to the second identifier, which does not identify any code segment.
[0168] As can be seen from the foregoing, multiple code segments can be executed through the first thread. If step 208 is not executed after step 201 has been executed, then the out-of-order duration may be incorrectly calculated during the execution of the next code segment through the first thread.
[0169] For example, if the next code segment after the first code segment does not have a delay requirement, and step 208 is not executed, the value of the global variable will still be the first identifier. In this way, during the execution of the next code segment through the first thread, the first duration corresponding to the first code segment will be mistakenly taken as the out-of-order duration.
[0170] Therefore, step 208 can prevent erroneous calculation of out-of-order duration.
[0171] It should be noted that step 208 is optional. Normally, step 208 will be executed when step 201 is executed.
[0172] It is understandable that the first duration is obtained based on the latency requirement, but the first duration may not be accurate enough. Therefore, the first duration can be adjusted after the first code segment is run. For example, since the first duration is obtained based on the latency requirement, it can be adjusted based on the latency requirement and using a feedback mechanism. This will be explained in steps 209 and 210 below.
[0173] Step 209: Obtain the actual execution time of the first code segment.
[0174] As can be seen from the foregoing description, while performing the first operation, the timestamp of the start of the first code segment is recorded; based on this, step 209 may include: obtaining the timestamp of the end of the first code segment, and then calculating the actual running time of the first code segment based on the timestamp of the start of the run and the timestamp of the end of the run.
[0175] Step 210: Based on the relative magnitude between the actual running time and the target latency, adjust the first duration. The target latency is the running latency of the first code segment as expected by the user.
[0176] As one possible approach, step 210 includes: shortening the first duration based on the fact that the actual running duration is greater than the target latency.
[0177] It should be noted that there are multiple methods to shorten the first duration, and this application does not specifically limit this method; for example, the first duration can be shortened by half.
[0178] As one possible approach, step 210 includes: extending the first duration based on the fact that the actual running time is less than the target delay.
[0179] It should be noted that there are various methods to extend the first duration, and this application embodiment does not specifically limit this method; for example, the first duration can be extended by one unit each time; in order to prevent the actual running time from exceeding the target delay again after extending the first duration, the adjustment of one unit is generally smaller than the reduction in the previous shortening of the first duration.
[0180] For example, the adjustment range can be (100-PCT) / PCT, which is the reduction range in the previous process of shortening the first duration. Here, PCT is the tail delay indicator of the target delay. For example, if the target delay is set to P99 tail delay, then the PCT is 99, and the adjustment range is 1 / 99 of the reduction range in the previous process of shortening the first duration.
[0181] Tail delay refers to a specific delay, and in all runs of the first code segment, the delay of most runs will be less than this specific delay; for example, P99 tail delay means that in all runs of the first code segment, the delay of 99% of runs will be less than this specific delay.
[0182] Therefore, in this embodiment, once the actual running time exceeds the set target latency, the first duration will be halved, and subsequent increases will be 1 / 99 of the reduction. If the execution situation does not change, the subsequent 99 latency adjustments will not exceed the target latency.
[0183] The following describes the case where the first code segment does not have latency requirements, such as... Figure 5 As shown, this application provides a third embodiment of a method for acquiring lock resources, which includes:
[0184] Step 401: Determine that the priority of the first core is lower than that of the second core.
[0185] Step 401 is similar to step 202. For details, please refer to the relevant explanation of step 202 in the previous text to understand step 401.
[0186] Step 402: Obtain the out-of-order duration.
[0187] Since there is no latency requirement for the first code segment in this embodiment, step 402 is different from step 203.
[0188] Specifically, as a feasible approach, such as Figure 6 As shown, step 402 includes:
[0189] Step 501: Determine that there is no latency requirement in the first code segment.
[0190] There are multiple methods to determine that the first code segment does not have a latency requirement, and this application does not specifically limit the methods.
[0191] If step 201 is performed, step 501 may include:
[0192] The value of the global variable is the second identifier, which determines that the first code segment does not have a delay requirement. The global variable represents the code segment with a delay requirement, while the second identifier does not identify any code segment.
[0193] Since global variables have been explained in the previous text, they will not be repeated here.
[0194] Step 502: Based on the fact that there is no delay requirement in the first code segment, obtain the second duration as the out-of-order duration.
[0195] It should be noted that, since the first code segment does not have a latency requirement, theoretically, the out-of-order duration can be very long; however, in order to prevent the first thread from being in a backoff state indefinitely, causing the first code segment to be unable to continue running, this embodiment uses a second duration with a limited length as the out-of-order duration.
[0196] However, since the first code segment does not have a latency requirement, the second duration is usually longer than the first duration. Based on this, the second duration can also be called the maximum out-of-order duration.
[0197] In addition, the first duration can be dynamically adjusted based on latency requirements, unlike the second duration, which can be fixed.
[0198] Step 403: If the waiting queue is not empty, the first thread enters the backoff state, which is the state of waiting to be added to the waiting queue.
[0199] Step 403 is similar to step 204. For details, please refer to the relevant explanation of step 204 in the previous text to understand step 403.
[0200] Step 404: Based on the fact that the duration of entering the backoff state is greater than or equal to the out-of-order duration, add it to the waiting queue.
[0201] Step 404 is similar to step 205. For details, please refer to the relevant explanation of step 205 above to understand step 404.
[0202] Step 405: Based on the fact that the duration of entering the backoff state is less than the out-of-order duration, the waiting queue is detected.
[0203] Step 405 is similar to step 206. For details, please refer to the relevant explanation of step 206 in the previous text to understand step 405.
[0204] Step 406: If the waiting queue is empty, add it to the waiting queue.
[0205] Step 406 is similar to step 207. For details, please refer to the relevant explanation of step 207 in the previous text to understand step 406.
[0206] To facilitate understanding, the following will be combined with... Figure 7 The process of adding the first thread to the waiting queue is explained.
[0207] Specifically, the first thread determines that the priority of the first core is lower than the priority of the second core, and then enters a backoff state (i.e., Figure 7 As shown in a. Delayed addition to the waiting queue); after the first thread enters the backoff state, the second thread running under the second core adds to the tail of the waiting queue, and the lock will be passed down from the lock holder to the second thread in the waiting queue.
[0208] When the disordered duration ends ( Figure 7 (shown as b) after, or when the waiting queue is empty ( Figure 7 When (as shown in c), the first thread joins the tail of the waiting queue to acquire the lock.
[0209] The methods provided in the embodiments of this application have been described above. The application scenarios of the methods provided in the embodiments of this application will be described below.
[0210] Specifically, the method provided in this application embodiment can be applied to any application, and there are various specific application methods.
[0211] For example, for a typical application, the method provided in this application embodiment can be implemented by modifying the application's code; for example, the application includes a code segment containing locking code, and the locking code in the code segment can be modified so that the first thread performs the first operation mentioned above during the execution of the modified locking code; in addition, corresponding code can be added before and after the locking code so that the first thread performs the second operation mentioned above during the execution of the code before the locking code, and performs the third operation mentioned above during the execution of the code after the locking code.
[0212] It is understandable that making extensive modifications to the application code would result in a large workload. In order to reduce the workload and enhance the practicality of the method provided in this application embodiment, the following methods can be used to improve the application.
[0213] like Figure 8 As shown, the application includes a latency-critical code segment (i.e., the first code segment mentioned above), which is referred to as epoch in this embodiment. The latency-critical code segment contains code related to mutexes. When the code related to mutexes is executed, mutex-related operations are performed. These mutex-related operations may include calling the function pthread_mutex_lock, which is used to enable a thread to acquire a mutex.
[0214] To minimize modifications to the original application code, this embodiment adds a target library containing mutex-related code. When the mutex-related code in the target library is run, mutex-related operations are also performed; furthermore, a redirection method is used. Figure 8Using marker ③, the mutex-related operations performed when the above latency-critical code snippet is executed, and the mutex-related operations performed when the target library's code related to mutexes (e.g., the first operation) are executed; thus, when the first thread calls the function pthread_mutex_lock, the first operation will be automatically executed. Figure 8 Using ④ as a marker), this first operation is used to enable the first thread to acquire the out-of-order lock provided in the embodiments of this application. Figure 8 Using the ⑤ label), as can be seen from the foregoing description, this out-of-order lock is established based on an existing FIFO lock.
[0215] Redirection is the process of redirecting network requests to other locations using various methods.
[0216] Therefore, when there is no latency requirement, for existing applications, this embodiment only needs to add a target library and redirect the mutex-related operations in the first code segment to the mutex-related operations in the target library, without modifying the application code.
[0217] As explained above, if the first code segment has a delay requirement, the first thread needs to perform a second operation before performing the first operation, and a third operation after performing the first operation.
[0218] The implementation methods for the second and third operations are as follows: Add the interface epoch_start before the first code segment (this interface marks the start of the epoch, Figure 8 Use ① as a marker) and the interface epoch_end (this interface marks the end of the epoch). Figure 8 Using the ② marker), the target library also includes code called through the epoch_star interface and code called through the epoch_end interface; when the first thread calls the epoch_star interface, it will run the code in the target library to perform the second operation mentioned above; when the first thread calls the epoch_end interface, it will run the code in the target library to perform the third operation mentioned above.
[0219] Therefore, even if the first code segment has latency requirements, only two interfaces need to be added to the application code, without requiring much modification to the application code, and the workload is small.
[0220] As explained above, the first thread performs the first operation during the execution of the first code segment, thereby acquiring a scrambled lock. It should be noted that this embodiment does not specifically limit the number of scrambled locks; the number of scrambled locks can be one or more. When the number of scrambled locks is multiple, it means that the first thread needs to perform the first operation multiple times to acquire multiple scrambled locks, and the multiple scrambled locks can be different locks.
[0221] Furthermore, when there are multiple out-of-order locks, these locks can be nested or associated through interfaces such as condition variables or trylock.
[0222] Based on the descriptions of the three embodiments above, there are three situations in which the first thread is added to the waiting queue: the first situation is that the priority of the first core is higher than the priority of the second core; the second situation is that the priority of the first core is lower than the priority of the second core, but the first code segment has a latency requirement; and the third situation is that the priority of the first core is lower than the priority of the second core, but the first code segment does not have a latency requirement.
[0223] The operations performed by the first thread differ for these three scenarios. To facilitate differentiation, this application provides a corresponding interface for each scenario.
[0224] Specifically, such as Figure 9 As shown, assuming multiple cores of a computer device correspond to two priorities; the first thread joining the waiting queue includes:
[0225] The first thread first determines whether the first core is a large core (i.e., whether it has high priority);
[0226] If the first core is a large core (i.e., high priority), the first thread calls the lock_immediately interface to directly join the waiting queue, and eventually the lock is successfully acquired;
[0227] If the first core is not a large core (i.e., low priority), then the first thread determines whether it is in an epoch (i.e., whether there is a latency requirement);
[0228] If the first core is not a large core and is in an epoch (i.e., there is a latency requirement), then the first thread calls the interface ock_reorder to add it to the waiting queue by executing steps 203 to 210, and finally successfully acquires the lock.
[0229] If the first core is not a large core and is not in the epoch (i.e., there is a latency requirement), then the first thread calls the interface ock_eventually to add it to the waiting queue by executing steps 402 to 40, and finally successfully acquires the lock.
[0230] Understandably, during the process of acquiring the lock, the first thread needs to join the waiting queue. The three scenarios for the first thread joining the waiting queue have been described above. After acquiring the lock, the first thread will execute the critical section. After executing the critical section, the first thread will release the lock. The process of releasing the lock will be briefly explained below.
[0231] As explained above, the mutex-related operations in the first code segment can include calling the function pthread_mutex_lock, which is used to enable the thread to acquire the mutex; in addition, the mutex-related operations in the first code segment can also include calling the function pthread_mutex_unlock, which is used to enable the thread to release the lock.
[0232] Because the mutex-related code in the first code segment is redirected to the mutex-related code inside the target library, when the first thread calls the function pthread_mutex_unlock, the operation of releasing the out-of-order lock inside the target library will be automatically executed. The operation of releasing the out-of-order lock is the same for the three cases mentioned above where the lock is added to the waiting queue.
[0233] In order to demonstrate the beneficial effects of the method provided in the embodiments of this application, the applicant conducted the following tests.
[0234] Figure 10 The graph shows the ratio of throughput using the target library (LibASL) to throughput using other locks (such as Spinlock, Ticket lock, MCS lock, and Pthread mutex), and whether the actual execution time of the code segment can reach the set target latency SLO; where the horizontal axis represents different target latency SLO settings, and the vertical axis represents the ratio of throughput.
[0235] like Figure 10 As stated, when the set latency is 6*104ns, using the target library (LibASL), LibASL's throughput is 1.2 times that of the spinlock (i.e., a performance improvement of 20%); and at this time, the actual tail latency of all cores is 0.948 times that of the set SLO (6*104ns), and the tail latency of the small core is 1.002 times that of the set SLO (6*104ns). Figure 10 (Not shown).
[0236] besides, Figure 10Vertical dashed lines are also used to represent latency when using other locks. For example, when using spin locks, the total spin latency for all cores is 10.4 * 10⁴ ns, while the spin latency for the little cores is 13.1 * 10⁴ ns.
[0237] Therefore, it can be seen that when a reasonable SLO is set, the tail latency of LibASL (whether it is the tail latency of the little core or all cores) can be guaranteed (i.e., less than the SLO); in terms of throughput, compared with Ticket lock, MCS lock and Pthread mutex lock, LibASL can improve throughput by 40% to 66% while ensuring the target latency is met; and compared with spin lock, LibASL can improve throughput by 40% while having the same tail latency of the little core.
[0238] Figure 11 This graph shows the latency of each epoch within the first 350ms of the test. The horizontal axis represents the time axis from 0 to 350ms, while the vertical axis represents the epoch latency. The solid horizontal line (10*104ns) indicates the current set latency SLO. In the test, we increased the epoch length (i.e., the execution time) by a factor of 8 at 100ms; restored the epoch length to its initial length at 200ms; frequently varied the epoch length starting at 250ms; and finally increased the epoch length by a factor of 128 at 300ms. The red and green dots in the graph represent the execution latency of all epochs on a small core and a large core, respectively.
[0239] from Figure 11 As can be seen, from 0 to 25ms, the out-of-order duration on the small cores gradually increases, leading to a gradual increase in latency, eventually reaching approximately the set SLO size at 25ms. At this point, the latency on the large cores also gradually decreases. From 25ms to 100ms, the out-of-order duration is adjusted repeatedly to ensure latency fluctuates within the SLO's allowable limits. When the epoch length is increased by 8 times at 100ms, LibASL can quickly adapt to the new epoch length, reducing the out-of-order duration to ensure the epoch latency remains within the set SLO range. Similarly, when the epoch length is restored at 200ms, LibASL can quickly adjust the out-of-order duration to maximize throughput. When the epoch length begins to fluctuate frequently at 250ms, LibASL can still ensure latency remains within the SLO. Finally, at 300ms, because the epoch length increases by 128 times, the set SLO cannot be guaranteed; therefore, LibASL is not used at this point to ensure latency consistency across all cores as much as possible. Therefore, it can be seen from... Figure 11 As can be seen, the latency is the same on both the big core and the small core at this time.
[0240] like Figure 12 As shown in the embodiment of this application, an apparatus for acquiring lock resources is also provided, applied to a computer device. The processor of the computer device includes a first core and a second core. The apparatus includes: a determining unit 601, used to determine that the priority of the first core is lower than the priority of the second core; and a queue joining unit 602, used to delay joining the waiting queue when the waiting queue is not empty, so that the second thread running under the second core joins the waiting queue before the first thread, and the waiting queue is used to compete for lock resources.
[0241] As one possible approach, the determining unit 601 is used to determine that the priority of the first core is lower than that of the second core based on the fact that the performance of the second core is better than that of the first core.
[0242] As one possible approach, queue addition unit 602 is used to allow the first thread to enter a backoff state when the waiting queue is not empty. The backoff state is a state of waiting to be added to the waiting queue. The thread is added to the waiting queue based on the duration of entering the backoff state being greater than or equal to the out-of-order duration.
[0243] As one possible approach, queue addition unit 602 is used to obtain the out-of-order duration.
[0244] As one possible approach, queue addition unit 602 is used to obtain the first duration corresponding to the first code segment as the out-of-order duration based on the existence of a delay requirement in the first code segment. The first duration is obtained based on the delay requirement.
[0245] As one possible implementation, the device further includes: a first setting unit 603, used to set the value of a global variable to a first identifier of a first code segment, wherein the global variable represents a code segment with a latency requirement; and a queue joining unit 602, used to determine that the first code segment has a latency requirement based on the value of the global variable being the first identifier.
[0246] As one possible implementation, the device also includes a second setting unit 604, used to set the value of the global variable to a second identifier, wherein the second identifier does not identify any code segment.
[0247] As one possible approach, the device further includes: an adjustment unit 605, used to obtain the actual running duration of the first code segment; and to adjust the first duration based on the relative magnitude between the actual running duration and the target delay specified by the delay requirement.
[0248] As one possible approach, the adjustment unit 605 is used to shorten the first duration based on the actual running duration being greater than the target delay.
[0249] As one possible approach, the adjustment unit 605 is used to extend the first duration based on the fact that the actual running time is less than the target delay.
[0250] As one possible approach, queue addition unit 602 is used to obtain the second duration as the out-of-order duration based on the fact that there is no delay requirement in the first code segment.
[0251] As one possible approach, queue addition unit 602 is used to determine that the first code segment does not have a delay requirement based on the value of the global variable as the second identifier. The global variable represents the code segment with a delay requirement, and the second identifier does not identify any code segment.
[0252] As one possible approach, the queue addition unit 602 is used to detect the waiting queue based on the fact that the duration of entering the backoff state is less than the out-of-order duration; and to add to the waiting queue if the waiting queue is empty.
[0253] As one possible approach, queue addition unit 602 is used to add to the waiting queue when the waiting queue is empty.
[0254] For details on the implementation, related explanations, and technical effects of each of the above units, please refer to the description in the aforementioned methods section.
[0255] Please see Figure 13 , Figure 13 This is a schematic diagram of a computer device provided in an embodiment of this application, used to implement... Figure 11 In accordance with the function of the device for acquiring lock resources in the corresponding embodiment, specifically, the computer device 1800 is implemented by one or more servers. The computer device 1800 can vary significantly due to different configurations or performance, and may include one or more central processing units (CPUs) 1822 (e.g., one or more processors) and memory 1832, and one or more storage media 1830 (e.g., one or more mass storage devices) for storing application programs 1842 or data 1844. The memory 1832 and storage media 1830 can be temporary or persistent storage. The program stored in the storage media 1830 may include one or more modules (not shown in the figure), each module may include a series of instruction operations on the computer device. Furthermore, the CPU 1822 may be configured to communicate with the storage media 1830 and execute the series of instruction operations in the storage media 1830 on the computer device 1800.
[0256] The computer device 1800 may also include one or more power supplies 1826, one or more wired or wireless network interfaces 1850, one or more input / output interfaces 1858, and / or one or more operating systems 1841, such as Windows Server™, Mac OS X™, Unix™, Linux™, FreeBSD™, etc.
[0257] In this embodiment of the application, the central processing unit 1822 can be used to execute... Figure 11 The corresponding embodiment describes the method for acquiring lock resources executed by the device for acquiring lock resources. Specifically, the central processing unit 1822 can be used for:
[0258] The first code segment is executed by running the first thread on the first core to perform the following first operation:
[0259] The priority of the first core is determined to be lower than that of the second core;
[0260] If the waiting queue is not empty, the thread is added to the waiting queue with a delay, so that the second thread running on the second core can be added to the waiting queue before the first thread. The waiting queue is used to compete for lock resources.
[0261] This application also provides a chip including one or more processors. Part or all of the processors are used to read and execute computer programs stored in a memory to perform the methods of the foregoing embodiments.
[0262] Optionally, the chip includes a memory, which is connected to the processor via a circuit or wire. Further optionally, the chip also includes a communication interface, to which the processor is connected. The communication interface is used to receive data and / or information that needs to be processed. The processor obtains the data and / or information from the communication interface, processes the data and / or information, and outputs the processing result through the communication interface. The communication interface can be an input / output interface.
[0263] In some implementations, some of the processors may implement some steps of the above method through dedicated hardware. For example, the processing of neural network models may be implemented by a dedicated neural network processor or graphics processor.
[0264] The method provided in this application embodiment can be implemented by a single chip or by multiple chips working together.
[0265] This application also provides a computer storage medium for storing computer software instructions for use with the aforementioned computer device, including instructions for executing programs designed for the computer device.
[0266] The computer device can be as described above. Figure 11 The apparatus for acquiring lock resources in the corresponding embodiment.
[0267] This application also provides a computer program product, which includes computer software instructions that can be loaded by a processor to implement the processes in the methods shown in the foregoing embodiments.
[0268] Those skilled in the art will clearly understand that, for the sake of convenience and brevity, the specific working processes of the systems, devices, and units described above can be referred to the corresponding processes in the foregoing method embodiments, and will not be repeated here.
[0269] In the several embodiments provided in this application, it should be understood that the disclosed systems, apparatuses, and methods can be implemented in other ways. For example, the apparatus embodiments described above are merely illustrative; for instance, the division of units is only a logical functional division, and in actual implementation, there may be other division methods. For example, multiple units or components may be combined or integrated into another system, or some features may be ignored or not executed. Furthermore, the coupling or direct coupling or communication connection shown or discussed may be an indirect coupling or communication connection between apparatuses or units through some interfaces, and may be electrical, mechanical, or other forms.
[0270] The units described as separate components may or may not be physically separate. The components shown as units may or may not be physical units; that is, they may be located in one place or distributed across multiple network units. Some or all of the units can be selected to achieve the purpose of this embodiment according to actual needs.
[0271] Furthermore, the functional units in the various embodiments of this application can be integrated into one processing unit, or each unit can exist physically separately, or two or more units can be integrated into one unit. The integrated unit can be implemented in hardware or as a software functional unit.
[0272] If the integrated unit is implemented as a software functional unit and sold or used as an independent product, it can be stored in a computer-readable storage medium. Based on this understanding, the technical solution of this application, in essence, or the part that contributes to the prior art, or all or part of the technical solution, can be embodied in the form of a software product. This computer software product is stored in a storage medium and includes several instructions to cause a computer device (which may be a personal computer, server, or network device, etc.) to execute all or part of the steps of the methods described in the various embodiments of this application. The aforementioned storage medium includes various media capable of storing program code, such as USB flash drives, portable hard drives, read-only memory (ROM), random access memory (RAM), magnetic disks, or optical disks.
Claims
1. A method for acquiring lock resources, characterized in that, Applied to computer equipment, wherein the processor of the computer equipment includes a first core and a second core; The method includes: The first code segment is executed by the first thread running on the first core to perform the following first operation: The priority of the first core is determined to be lower than that of the second core; If the waiting queue is not empty, the first thread delays joining the waiting queue so that the second thread running under the second core joins the waiting queue before the first thread. The waiting queue is used to compete for lock resources. The determination that the priority of the first core is lower than the priority of the second core includes: Based on the fact that the performance of the second core is better than that of the first core, the priority of the first core is determined to be lower than that of the second core. The first thread running on the first core takes longer to execute the critical section than the second thread running on the second core takes longer to execute the critical section. The critical section is executed according to the lock resource. The first operation also includes: Based on the latency requirement of the first code segment, the first duration corresponding to the first code segment is obtained as the out-of-order duration, and the first duration is obtained based on the latency requirement. The method further includes: Before running the first code segment, the following second operation is performed through the first thread: Set the value of the global variable to the first identifier of the first code segment, where the global variable represents the code segment with latency requirements; Before determining the first duration corresponding to the first code segment as the out-of-order duration based on the latency requirement of the first code segment, the first operation further includes: Based on the value of the global variable being the first identifier, it is determined that the first code segment has a latency requirement.
2. The method according to claim 1, characterized in that, The step of delaying joining the waiting queue when the waiting queue is not empty includes: If the waiting queue is not empty, the first thread enters a backoff state, which is a state of waiting to join the waiting queue; If the duration of entering the backoff state is greater than or equal to the out-of-order duration, the user is added to the waiting queue.
3. The method according to claim 1, characterized in that, The method further includes: After the first code segment is executed, the following third operation is performed through the first thread: Set the value of the global variable to the second identifier, which does not identify any code segment.
4. The method according to claim 1, characterized in that, The method further includes: After the first code segment is executed, the following third operation is performed through the first thread: Obtain the actual execution time of the first code segment; The first duration is adjusted based on the relative magnitude between the actual running time and the target latency specified by the latency requirement.
5. The method according to claim 4, characterized in that, Adjusting the first duration based on the relative magnitude between the actual running time and the target latency includes: Based on the fact that the actual running time is greater than the target latency, the first duration is shortened.
6. The method according to claim 4, characterized in that, Adjusting the first duration based on the relative magnitude between the actual running time and the target latency includes: Since the actual running time is less than the target delay, the first duration is extended.
7. The method according to claim 1, characterized in that, The first operation also includes: Since there is no latency requirement for the first code segment, the second duration is obtained as the out-of-order duration.
8. The method according to claim 7, characterized in that, After obtaining the second duration as the out-of-order duration based on the fact that there is no latency requirement for the first code segment, the first operation further includes: Based on the value of the global variable being the second identifier, it is determined that the first code segment has no latency requirement, and the second identifier does not identify any code segment.
9. The method according to claim 2, characterized in that, The method of delaying joining the waiting queue when the waiting queue is not empty also includes: The waiting queue is detected based on the fact that the duration of entering the backoff state is less than the out-of-order duration; If the waiting queue is empty, add the item to the waiting queue.
10. The method according to any one of claims 1 to 9, characterized in that, After determining that the first core has a lower priority than the second core, the first operation further includes: If the waiting queue is empty, add the item to the waiting queue.
11. An apparatus for acquiring lock resources, characterized in that, Applied to computer equipment, wherein the processor of the computer equipment includes a first core and a second core; The device includes: A determining unit is used to determine that the priority of the first core is lower than the priority of the second core; The queue addition unit is used to delay the first thread from joining the waiting queue when the waiting queue is not empty, so that the second thread running under the second core joins the waiting queue before the first thread. The waiting queue is used to compete for lock resources. The determination that the priority of the first core is lower than the priority of the second core includes: Based on the fact that the performance of the second core is better than that of the first core, the priority of the first core is determined to be lower than that of the second core. The first thread running on the first core takes longer to execute the critical section than the second thread running on the second core takes longer to execute the critical section. The critical section is executed according to the lock resource. The queue joining unit is also used for: Based on the latency requirement of the first code segment, the first duration corresponding to the first code segment is obtained as the out-of-order duration, and the first duration is obtained based on the latency requirement. The device further includes: The first setting unit is used to set the value of a global variable to the first identifier of the first code segment before running the first code segment, wherein the global variable represents a code segment with latency requirements; The queue joining unit is further configured to determine that the first code segment has a delay requirement based on the value of the global variable and the first identifier before using the first duration corresponding to the first code segment as the out-of-order duration, based on the existence of a delay requirement in the first code segment.
12. A computer device, characterized in that, The method includes a memory and a processor, wherein the memory is used to store computer-readable instructions; and the processor is used to read the computer-readable instructions and implement the method as described in any one of claims 1-10.
13. A computer storage medium, characterized in that, The device stores computer-readable instructions, which, when executed by a processor, implement the method as described in any one of claims 1-10.
14. A computer program product, characterized in that, The computer program product includes computer-readable instructions that, when executed by a processor, implement the method as described in any one of claims 1-10.
Citation Information
Patent Citations
Systems and Methods for Performing Concurrency Restriction and Throttling over Contended Locks
US20170039094A1