Multi-threaded data dependency
By introducing decoder circuits to generate prompts and virtual dependency mechanisms in a multi-threaded environment, the problem of difficult data dependency detection is solved, parallel execution between loop iterations is realized, and the parallelism and efficiency of micro-threads are improved.
Patent Information
- Application Number
- CN202480017767.7
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Priority Date
- 2023-03-23
- Filing Date
- 2024-02-27
- Publication Date
- 2025-10-31
AI Technical Summary
In a multithreaded environment, data dependencies are difficult to detect and respond to, making parallel tasks difficult to execute, especially when there are cross-iteration data dependencies in loops, which existing technologies cannot handle effectively.
By introducing decoder circuits to generate prompts indicating resource availability and demand, and using virtual dependency mechanisms to control the execution order of microthreads, including mailbox circuits and register checking mechanisms, parallelization is achieved by ensuring that resources are used only when they are available.
It effectively solves the data dependency problem, realizes parallel execution between loop iterations, and improves the parallelism and execution efficiency of microthreads.
Smart Images

Figure CN120883183A_ABST
Abstract
Description
[0001] This technology involves data processing, especially in multithreaded environments.
[0002] The goal is to provide a microarchitectural, multithreaded environment. As with microarchitecture, the environment doesn't need to be visible to the programmer, or even known to them. However, as a result, data dependencies can be difficult to detect and respond to.
[0003] From the first example configuration, a data processing apparatus is provided, comprising: a multi-threaded processing circuit for executing processing operations of multiple micro-threads, each micro-thread operating in a corresponding execution context of a defined architectural state; and a decoder circuit that generates a first micro-thread for a first instruction block in response to a first occurrence of a detach instruction, and generates a second micro-thread for a second instruction block in response to a second occurrence of the detach instruction, wherein the second instruction block includes data dependencies regarding resources accessed in the first instruction block.
[0004] From the second example configuration, a method is provided, which includes: performing processing operations on multiple microthreads, each microthread operating in a corresponding execution context of a defined architectural state; generating a first microthread for a first instruction block in response to the first occurrence of a detach instruction; and generating a second microthread for a second instruction block in response to the second occurrence of the detach instruction, wherein the second instruction block includes data dependencies on resources accessed in the first instruction block.
[0005] From the third example configuration, a non-transitory computer-readable medium is provided for storing computer-readable code for manufacturing a data processing apparatus, the data processing apparatus comprising: multi-threaded processing circuitry for performing processing operations of a plurality of micro-threads, each micro-thread operating in a corresponding execution context of a defined architectural state; and decoder circuitry for generating a first micro-thread for a first instruction block in response to a first occurrence of a detach instruction, and for generating a second micro-thread for a second instruction block in response to a second occurrence of the detach instruction, wherein the second instruction block includes data dependencies regarding resources accessed in the first instruction block.
[0006] From the fourth example configuration, a data processing apparatus is provided, comprising: an input circuit configured to receive an input code including a first instruction block and a second instruction block; an output circuit configured to generate output codes corresponding to the first instruction block and the second instruction block; and a processing circuit configured to generate the output codes based on the input codes, wherein the processing circuit is configured to generate: a first prompt instruction corresponding to the first instruction block within the output codes, the first prompt instruction being configured to indicate resource availability; and a second prompt instruction corresponding to the second instruction block within the output codes, the second prompt instruction being configured to indicate a request for the resource; and the second instruction block including data dependencies regarding the resource accessed in the first instruction block.
[0007] From the fifth example configuration, a method is provided, which includes: receiving an input code including a first instruction block and a second instruction block; generating an output code corresponding to the first instruction block and the second instruction block; and generating the output code based on the input code, wherein the output code includes: a first prompt instruction corresponding to the first instruction block within the output code, the first prompt instruction being configured to indicate the availability of a resource, and a second prompt instruction corresponding to the second instruction block within the output code, the second prompt instruction being configured to indicate a request for the resource; and the second instruction block includes data dependencies regarding the resource accessed in the first instruction block.
[0008] From the sixth example configuration, a non-transitory computer-readable medium is provided for storing computer-readable code for manufacturing a data processing apparatus. The data processing apparatus includes: an input circuit configured to receive input code including a first instruction block and a second instruction block; an output circuit configured to generate output code corresponding to the first instruction block and the second instruction block; and a processing circuit configured to generate the output code based on the input code, wherein the processing circuit is configured to generate: a first prompt instruction corresponding to the first instruction block within the output code, the first prompt instruction being configured to indicate resource availability; and a second prompt instruction corresponding to the second instruction block within the output code, the second prompt instruction being configured to indicate a request for the resource; and the second instruction block includes data dependencies regarding the resource accessed in the first instruction block.
[0009] The invention will be further described by way of example only, with reference to embodiments illustrated in the accompanying drawings, wherein:
[0010] Figure 1 Data processing apparatuses that embody various examples of the present technology are illustrated schematically;
[0011] Figure 2 The details of the operation of thread control circuitry, which can embody various examples of this technology, are illustrated schematically.
[0012] Figure 3A The details of the assignment of epoch identifiers are illustrated schematically in various examples that can embody this technology.
[0013] Figure 3B The details of the assignment of epoch identifiers are illustrated schematically in various examples that can embody this technology.
[0014] Figure 4 The details of microthread execution, which can embody various examples of this technology, are illustrated schematically.
[0015] Figure 5 The details of microthread execution, which can embody various examples of this technology, are illustrated schematically.
[0016] Figure 6 This example illustrates two prompts that help overcome data dependency limitations;
[0017] Figure 7 An example of execution is shown;
[0018] Figure 8 An example is given of a specific implementation of a data processing device for handling two microthreads;
[0019] Figure 9 Two additional hint instructions are illustrated that can be used to indicate the availability of other resources (such as memory addresses or code blocks) and expectations of those other resources;
[0020] Figure 10 An example of an 8-bit register (tkn) used to support 8 semaphores is shown;
[0021] Figure 11 Another example of execution is shown;
[0022] Figure 12 The compiler is illustrated;
[0023] Figure 13A and Figure 13B This example illustrates the compiler's behavior regarding the placement of prompt instructions;
[0024] Figure 14 This illustrates another mechanism that can be used to manage dependencies; and
[0025] Figure 15 A pair of flowcharts are shown.
[0026] Before discussing the implementation scheme with reference to the accompanying drawings, the following description of the implementation scheme and its associated advantages is provided.
[0027] According to an example configuration, a data processing apparatus is provided, comprising: multithreaded processing circuitry for executing processing operations of multiple microthreads, each microthread operating in a corresponding execution context defined by an architectural state; and decoder circuitry that generates a first microthread for one iteration of a loop in response to a first occurrence of a detach instruction, and generates a second microthread for another iteration of the loop in response to a second occurrence of the detach instruction, wherein the loop includes loop-carried data dependencies regarding resources that extend across iterations of the loop. The creation of microthreads via detach instructions can be used to parallelize tasks, such as executing code belonging to a loop. This parallelization can be handled by the microarchitecture via detach instructions and is therefore invisible to the operating system. This parallelization can be problematic in loops where data dependencies extend across iterations of the loop. For example, if an iteration of the loop requires data provided in a previous iteration of the loop, it makes sense that the previous iteration of the loop should be completed before the "current" iteration of the loop can be executed. In other words, if the required data is unavailable before a previous iteration completes, the current iteration, which depends on the required data, cannot be executed. This technique introduces one or more mechanisms in which the previously described parallelization can still occur regardless of data dependencies.
[0028] In some examples, the data dependency carried by the loop is a write-after-read data dependency on the resource. That is, the resource is written in one iteration of the loop and read in a later iteration of the loop. Therefore, the value read in a later iteration of the loop is derived from (or is actually a value written in an earlier iteration) the value written in an earlier iteration.
[0029] In some examples, the decoder circuitry responds to: a first cue instruction configured to indicate resource availability when executed in a first microthread, and a second cue instruction configured to indicate a request for the resource when executed in a second microthread. The first cue instruction indicates resource availability; for example, this may occur after the resource has been written. The second cue instruction indicates resource requirement; for example, this may occur before the resource has been read. By using both instructions across loop iterations, signals of desired / available resources can be signaled across iterations.
[0030] In some examples, resources are one of the following: registers, variables, memory locations, and code blocks. By treating code blocks as resources, access to the code can be controlled so that only one microthread can exist within the block at a time. For example, this can be used to avoid race conditions between microthreads. Variables can be stored, for example, in memory. This adds another level of complexity because dependencies due to the dynamic nature of memory access may not be known at compile time. Supporting dependencies through memory can improve the parallelism of microthreads.
[0031] In some examples, depending on whether a condition is met, the decoder circuitry responds to a second cue instruction by creating a virtual dependency; and depending on whether a condition is met, the decoder circuitry responds to a first cue instruction by resolving the virtual dependency. Dependencies can be used to control how the microarchitecture processes cue instructions. Virtual dependencies allow control over the execution order of instructions and the other instructions that those instructions depend on.
[0032] In some examples, virtual dependencies are virtual dependencies on registers. Regardless of the nature of the resource, virtual dependencies (e.g., between hint instructions and therefore between other instructions that the hint instructions depend on) can themselves depend on registers. That is, the hinting mechanism that exists is implemented based on registers, and in practice, registers can simply indicate the availability (or unavailability) of another resource (such as a variable or a block of code).
[0033] In some examples, the registers are physical registers. Physical registers are registers backed by physical devices. This differs from logical / architectural registers, which are conceptual (virtual) registers. Typically, instructions will refer to the architecture register, which indicates how registers are logically related to each other. The renaming circuitry is responsible for mapping architecture registers to physical registers and, at execution time, replacing references to architecture registers with references to physical registers to remove erroneous instruction dependencies.
[0034] In some examples, the data processing apparatus includes: a mailbox circuit configured to store resources that have become available, wherein a first prompt instruction is prevented from being issued until there is free capacity in the mailbox circuit; in response to issuing the first prompt instruction, a new entry for the resource is inserted into the mailbox circuit; a second prompt instruction cannot be issued until a corresponding entry for the resource exists in the mailbox circuit; and in response to the completion of the second prompt instruction, the corresponding entry for the resource is removed from the mailbox circuit. The mailbox circuit can be used to implement virtual dependencies. Specifically, when the first prompt instruction is issued (which requires the mailbox circuit to have free capacity), it causes a new entry to be inserted into the mailbox circuit to indicate the availability of the resource specified by the first prompt instruction. The second prompt instruction cannot be executed until the resource mentioned by the second prompt instruction is listed in the mailbox circuit (thus indicating the availability of the resource). When the second prompt instruction has been completed (e.g., execution ends), the entry for the resource is removed from the mailbox circuit (this may include invalidating it in the mailbox circuit), thereby revoking the "availability" of the resource (marking it as unavailable again). These later instructions are prevented from being issued due to the dependency of later instructions on the resource within each micro-thread referencing the same resource. Other instructions, independent of resources, can be freely executed, and thus restricted forms of parallelization are possible. In some examples, a second cue instruction cannot be issued until a corresponding entry for the resource from a previous iteration exists in the mailbox circuit. In cases where multiple microthreads are waiting for a resource, availability is indicated to the microthread with the previous epoch ID (the epoch ID is assigned to each microthread to reflect the order of execution in the original program of the code executed by that microthread).
[0035] In some examples, virtual dependencies are only resolvable as a result of the first prompt instruction being executed. That is, there is no other way to make a resource available except through the first prompt instruction. This allows for strict control over resources, ensuring that a single iteration of the loop can only use the resource if it has been explicitly indicated as available in a previous iteration.
[0036] In some examples, the decoder circuitry responds to a reattachment instruction in a specific microthread of the instruction to indicate the availability of each resource used by that specific microthread of the instruction to a newer microthread of the instruction, and to terminate that specific microthread of the instruction. As a fault-protection mechanism, the action of reattaching a specific microthread (e.g., ending the parallelism of that specific microthread) acts as an implicit first cue instruction for all resources used by that microthread when no explicit first cue instruction is provided. That is, if the executing microthread of iteration N of the loop does not explicitly make a resource available, all resources used in that microthread are indicated as available for iterations > N in the loop. Note that in some implementations, resources will be made available for iteration N+1, i.e., the next iteration of the loop.
[0037] In some examples, depending on whether a condition is met, the decoder circuit responds to the first and second prompt instructions by generating a no-operation signal. If the condition is not met, the prompt instruction can simply have no effect by being decoded as a no-operation instruction. Therefore, the prompt instruction does not need to be followed and can actually be ignored entirely. In some implementations, there may be multiple different conditions, all of which need to be met for the prompt instruction to be executed as an instruction other than a no-operation instruction.
[0038] In some examples, the condition is whether parallelization of multiple microthreads is allowed. For example, the microarchitecture may have been disabled or may not support microthreads. In this case, microthread instructions can simply be ignored. This control can be determined simply by registers or bits in registers. In some cases, parallelism may be disabled if, for example, the overhead of implementing parallelism is particularly high.
[0039] In some examples, the data processing apparatus includes: a register checking circuit configured to set a stale register flag in response to the acquisition of a stale register value; and a decoder circuit to determine whether a stale register flag has been set in response to a reattachment instruction in a specific microthread of the instruction, and to re-execute the specific microthread of the instruction in response to the setting of the stale register flag. In such implementations, rather than explicitly making the resource available and explicitly indicating the expectation of the resource, and providing a mechanism to combine demand and supply hints, the system simply assumes that the resource will be available. In many cases, this is not an unreasonable assumption. After all, microthreads for each iteration of a loop can be created sequentially. Therefore, it is likely that instructions providing the data needed for later iterations of the loop in earlier iterations of the loop will have already been executed. In these examples, the register checking circuit determines whether a stale register value has been accessed, i.e., a register value that is not the latest in the given program's sequential order. When this occurs, and when the microthread terminates (e.g., by a reattachment instruction), the situation is detected and the microthread is re-executed. In this scenario, it is now more likely that the correct value will be stored in the register, and therefore the microthread will retrieve the correct value when it is executed. It should be noted that, as in other implementations, the value stored in the register can be used to enforce control over another resource, such as a value stored in memory or even a block of code.
[0040] According to another example configuration, a data processing apparatus is provided, comprising: an input circuit configured to receive an input code including a loop; an output circuit configured to generate an output code including the loop; and a processing circuit configured to generate the output code based on the input code, wherein the processing circuit is configured to generate, within the body of the loop in the output code: a first prompt instruction configured to indicate resource availability, and a second prompt instruction configured to indicate a request for the resource; and the loop includes loop-carried data dependencies regarding the resource, the loop-carried data dependencies extending across iterations of the loop.
[0041] In these examples, the data processing device may take the form of a compiler (which could be a just-in-time compiler) or even part of a pipeline that dynamically processes incoming instructions to provide hints to later parts of the pipeline. Here, code, which may take the form of source code, bytecode, assembly code, or even processor instructions, is provided to the input circuitry. This code contains loops. The loop body contains a series of instructions that are repeatedly executed. Each iteration of the loop may contain slightly different parameters. The processing circuitry modifies at least some of the input code to produce output code. The output code also contains loops, although they may be in a different format. The loops themselves have loop-carried data dependencies regarding resources. These dependencies occur across iterations of the loop. That is, data required for one iteration of the loop is provided by another iteration. The processing performed by the processing circuitry includes introducing two hint instructions into the output code: one indicating the availability of the resource and another indicating a request for the resource.
[0042] In some examples, the data dependencies carried by the loop are read-after-write data dependencies of the resource. Therefore, in one iteration of the loop, the resource is written, and in a later iteration of the loop, the resource is read. Thus, the write to the resource in an earlier iteration affects the parameters used in later iterations of the loop.
[0043] In some examples, the processing circuitry is configured to place a second prompt instruction before or at the first use of the resource in the body of the loop; and the processing circuitry is configured to place a first prompt instruction at or after the last use of the resource in the body of the loop. By placing the first prompt instruction in such a location, a second instruction indicating the expectation of the resource will appear before the resource is used in the body of the loop. Similarly, by placing the second prompt instruction before or at the first use of the resource in the body, a first instruction indicating the availability of the resource will appear once the resource has been provided. In some embodiments, the second prompt instruction arrives before or at the first time the resource is read in the loop. Moreover, in some embodiments, the first prompt instruction arrives after or at the last time the resource is written in the loop. It should be noted that if, for example, the instruction performs multiple functions, the prompt instruction can be provided at a specific "location". For example, a particular instruction can write the resource while indicating its availability, thus acting as the first prompt instruction.
[0044] In some examples, the processing circuitry is configured to place the second and first prompt instructions such that at least a portion of the body of the loop is outside the region defined between the first and second prompt instructions. For example, the entire body of the loop may not fall within the first and second prompt instructions. It is precisely this instruction movement outside the region defined between the two prompt instructions that makes parallelization well possible. Specifically, even if a particular microthread may not be able to execute code falling within that region (due to resource unavailability), instructions outside that region can still be executed when the resource becomes available. Therefore, parallelization is possible. It should be noted that in some implementations, the first and second prompt instructions are placed to minimize the number of instructions in the loop between the first and second prompt instructions. This will, of course, maximize the potential for parallelization because it not only minimizes the number of operations that must be performed in one microthread before the resource becomes available to another microthread, but it also increases the number of instructions that can be executed in one microthread while waiting for the resource to become available to another microthread.
[0045] The specific implementation scheme will now be described with reference to the accompanying drawings.
[0046] Figure 1A data processing apparatus 10 is schematically illustrated, illustrating various examples of the present technology. The data processing apparatus 10 includes multithreaded processing circuitry 12 and thread control circuitry 14. Thread control circuitry 14 is adapted to support multiple microthreaded contexts 16. Multithreaded processing circuitry 12 is a set of multithreaded execution resources and includes multiple execution pipelines 18, a set of physical registers 20, an instruction cache 22, a level 1 data cache 26, and a level 2 cache 24. Each of the multiple execution pipelines includes fetch circuitry 28 for fetching instructions from the instruction cache 22. The fetched instructions are passed to decoding circuitry 30 and then to renaming circuitry 32, which generates control signals for other components of the multithreaded processing circuitry including thread control circuitry 14. Before passing the decoded instructions to the issuing circuit 43 for issuance to the execution circuit 36, the renaming circuit 32 maps multiple physical registers 20 to a corresponding set of architectural registers associated with the execution context being executed on pipeline 18, which may contain any number of execution stages, including but not limited to arithmetic logic units, floating-point units, and load / store units. Once the instructions have completed execution, they are passed to the write-back circuit 40. It will be apparent to those skilled in the art that the pipelines of components 28, 30, 32, 34, 36, and 40 are intended to illustrate a typical multithreaded data processing apparatus, and any pipeline component may be a dedicated component provided for each pipeline, or may be shared among any number of pipelines 18. For example, each pipeline 18 may have some dedicated pipeline components and some components shared with one or more other pipelines 18. However, additional structures not explicitly shown may be added to the data processing apparatus 10. It will also be apparent to those skilled in the art that the multithreaded processing circuit 12 may include a single pipeline 18 that interweaves its resources across multiple microthreaded contexts.
[0047] Figure 2 Details of the operation of thread control circuitry 14, which can embody various examples of the present technology, are schematically illustrated. In some embodiments, thread control circuitry 42 can provide... Figure 1 The thread control circuit 14. The thread control circuit 42 stores multiple counters for controlling and tracking different microthreads executing on the data processing device 10. Specifically, the thread control circuit 42 uses epoch counter 44 to track the earliest epoch identifier issued to the microthread having that epoch identifier and the latest epoch identifier issued to the microthread having that epoch identifier for a set of currently executing code (identified by a region identifier) represented by (detach, reattach) instruction pairs. In this way, and as will be discussed regarding Figure 3AFurther, an in-flight epoch identifier can be maintained for each region identifier. Additionally, thread control circuitry 42 can maintain an execution context table 46, which indicates each execution context currently maintained by the multithreaded processing device, its corresponding epoch identifier, and its corresponding region identifier. It will be apparent to those skilled in the art that the information shown to be maintained in execution context table 46 is not exhaustive, and any information associated with an execution context may also be stored therein. For example, execution context table 46 may maintain a mapping between physical registers and architecture registers allocated to each execution context. Furthermore, thread control circuitry maintains runtime data 48 based on indications of performance metrics related to processing operations. Runtime data may be continuously updated based on currently executing instructions and / or may be maintained independently for each region identifier. In this way, thread control circuitry can control and maintain whether additional microthreads should be generated for each region identifier, and if so, which epoch identifiers are associated with which execution context and which region identifier.
[0048] Figure 3A and 3B The details of the assignment of epoch identifiers are illustrated schematically in various examples that can embody this technique. From Figure 3A Initially, epoch identifier 50 is processed in a cyclic manner. When a new microthread is spawned, the thread control circuit allocates epoch identifiers in ascending order, and when the maximum supported epoch identifier is reached, the thread control circuit wraps back. This scheme is implemented using two counters that track the earliest epoch identifier 52 and the latest epoch identifier 54. As a new epoch identifier is allocated, the latest epoch identifier is incremented, and once the earliest epoch identifier has been allocated, it wraps back to zero. When a microthread is committed (which occurs sequentially), the earliest epoch identifier is incremented, thus releasing the epoch identifier for subsequent microthreads to use. Figure 2 As shown, the latest epoch counter 54 and the earliest epoch counter 52 are maintained for each region identifier.
[0049] like Figure 3BAs shown, for implementations supporting nested parallelization regions, the epoch identifier 56 associated with each microthread can be defined hierarchically. In the illustrated implementation, the epoch identifier 56 is defined by: an outermost identifier 58 associated with the outermost pair of (detach, reattach) instructions; an outermost identifier 60 defined by an outer pair of (detach, reattach) instructions nested within the outermost pair of (detach, reattach) instructions; an innermost identifier 62 associated with an inner pair of (detach, reattach) instructions nested within the outermost pair of (detach, reattach) instructions; and an innermost identifier 64 associated with the innermost pair of (detach, reattach) instructions nested within the innermost pair of (detach, reattach) instructions. It will be apparent to those skilled in the art that the four layers of epoch identifiers associated with nested (detach, reattach) instruction pairs are merely illustrative, and any number of sets of nested (detach, reattach) instruction pairs can be supported based on the described mechanism. In some implementations, the bit widths allocated to each layer in the epoch identifier layer can be dynamically changed by hardware at runtime, while in other implementations, the bit widths allocated to each layer in the epoch identifier layer can be statically determined. (Similar to...) Figure 3A In the example discussed, each of the outermost identifier 58, outer identifier 60, inner identifier 62, and innermost identifier 64 maintains a pair of counters associated with the earliest epoch identifier and the latest epoch identifier. Specifically, the outermost epoch identifier 58 is one of a set of available outermost identifiers 66 and is associated with the earliest outermost identifier 68 and the latest outermost identifier 70. Similarly, the allocation of each of the outer identifiers 60, 62, and 64 is maintained by the corresponding outer earliest identifier and outer latest identifier, inner earliest identifier and inner latest identifier, and innermost earliest identifier 74 and innermost latest identifier 76.
[0050] Figure 4 and Figure 5 Details of examples of microthread execution that embody various aspects of this technology are illustrated schematically. Specifically, these diagrams are based on the following example C code with corresponding assembly code;
[0051]
[0052]
[0053] In the illustrated example, the compiler makes the following modifications to the assembly code in order to utilize task-level parallelization as described in some embodiments of the invention.
[0054]
[0055] The detach instruction used in the modified assembly code above includes multiple inputs. The `loop_body` and `loop_cont` fields are the addresses of the detach and continuation instruction blocks, respectively. This can be encoded using program counter-based offsets to represent such addresses. If the detach block field corresponds to an instruction that follows the detach instruction in program order, the detach block field can be omitted. The `region_id` field is a region identifier that must be unique at runtime and associated with a specific commented region. In implementation, it is sufficient that the region identifier is unique only within region nesting, meaning that the same region identifier can be reused across different nestings. Metadata fields can capture additional information that can be passed to thread control circuitry. Specifically, metadata can be used to: encode the parallelization confidence level, which represents the probability of dynamic dependencies implemented at runtime, such as based on profiling data; encode the parallelization value level, for example by including additional information about the estimated length of parallel paths, represented in terms of the number of instructions, which can include best-case and worst-case instruction counts; and other information related to the type of expected dependencies in the region, such as the presence or absence of write-after-read conflicts. Similarly, the reattach instruction specifies the `loop_cont` address and the region identifier, and the synchronization instruction specifies the region identifier.
[0056] Figure 4The details of an example of microthread execution, illustrating one aspect of this technique, are illustrated schematically. Specifically, the thread executing the detach instruction (initially uthread0) continues execution from loop_body without changing its epoch identifier. The resulting microthread (initially uthread 1) begins execution from loop_cont with a newly assigned epoch identifier to reflect the fact that in the original serial program, the continuation path would execute sequentially after the detach path. In this case, uthread 0 continues (assuming successful execution without data conflicts) until it reaches the reattach instruction, and uthread1 begins at the continuation address, increments the value stored in register x10 by 1, compares the value stored in x10 with the value stored in x3, updates the condition flag based on the result, and then branches to loop_head. Execution of uthread1 continues from loop_head, where a detach instruction is issued, which generates microthread uthread 2 before uthread1's execution continues from loop_body (assuming successful execution without data conflicts) until the reattach instruction is reached. As shown in the figure, new microthreads are generated from each previous microthread and the process continues until the condition flag associated with the b.ne instruction is set to zero, i.e., the value stored in register x10 is equal to x3. At this point, the execution of the microthread that issued the synchronization instruction (uthreadn in this case) is suspended until all microthreads with earlier epoch identifiers have completed, i.e., they have successfully executed the reattachment instruction.
[0057] Figure 5Details of an example of microthread execution that can embody various aspects of this technology are illustrated schematically. Specifically, the thread executing the detach instruction (uthread0 in this case) continues execution from the continuation path (loop_cont) with a newly assigned epoch identifier, reflecting the fact that in the original serial program, the continuation path would be executed sequentially after the detach path (loop body). The resulting microthread (uthread 1) begins execution from the detach path (loop_body) with an epoch identifier inherited from its parent microthread. In this exemplary implementation, uthread0 executes instructions after loop_cont, first incrementing the value stored in x10 by 1, comparing the value in x10 with x3, and updating the condition flag based on the result, then branching to loop_head and re-executing the detach instruction. This causes a new microthread uthread 2 to be generated and continue from loop_body, where the updated value in register x10 is imported from the execution context associated with uthread0 into the execution context associated with uthread2. As shown in the figure, the microthread generated by uthread 0 continues until the condition flag associated with the b.ne instruction is set to zero, that is, the value stored in register x10 is equal to x3. At this point, a synchronization instruction is issued and the execution of uthread 0 is paused until all microthreads with earlier epoch identifiers have completed, that is, they have successfully executed the reattachment instruction.
[0058] In these examples, the detach instruction causes the creation of a microthread. The reattach instruction terminates the execution of the microthread.
[0059] Providing additional mechanisms for handling more complex dependencies of resources (e.g., registers, memory, code blocks) using the techniques described above might be appropriate. One scenario where this could occur is when each iteration of the loop depends on data modified in previous iterations of the loop. That is, the loop body contains RAW data dependencies that extend across iterations of the loop. For example, consider the following code:
[0060]
[0061] In this example, the variable "d" is used in each iteration of the `complex_update` function call. The result of the `complex_update` call is then stored as a new value for the variable "d," which is used in the next iteration. Depending on the nature of the variable "d" and specifically its storage location, handling this write-after-read dependency is either inefficient to resolve (and therefore, the use of microthreads may be prevented) or unresolved. For example, if the variable "d" is stored in memory, the RAW dependency may be detectable, and if detected, could lead to the subsequent microthread being invalidated and restarted. This could result in each microthread being invalidated, and therefore potentially the microthread being disabled. If the variable "d" is stored in a register, the RAW dependency might not be detected, as it is generally assumed that such dangers have been removed from the code at compile time.
[0062] Figure 6 Examples of two prompt instructions are shown that help overcome these limitations. Prompt instructions indicate the availability of a specific resource (sending) and the expectation of receiving a specific resource (receiving).
[0063] These instructions allow (where microthreads are permitted to execute in parallel) the propagation of resources in the form of registers and their stored values between microthreads (e.g., between loop iterations). When microthreading is not permitted, the instructions are simply ignored (e.g., decoded like NOP instructions).
[0064] In these examples, the architectural state of the microthread at the start is not exactly the same as the architectural state at the end of the previous iteration. Specifically, resources (e.g., registers) <registerid>The register (and its stored value) is not available for later iterations and will be provided later via a receive instruction. The register cannot be read within the microthread until a receive instruction is encountered. Note that other instructions, not dependent on the resource, are still executable. Therefore, some level of parallelism can still be achieved. The send instruction thus provides that the sequential program flow should wait until an indication that the resource (e.g., a register) is available.
[0065] Instead, a command is sent to indicate that the resource is available. This indication is then sent to the next iteration of the loop.
[0066] value <regionid>It is a value used to uniquely identify a loop or other data structure, and therefore can be used to disambiguate between inner and outer loops. ID can be the program counter value of the starting address of a contiguous block of the loop (typically a block of code that handles loop maintenance / inductive variable updates when the loop is repeated, not when it ends).
[0067] parameter <messageid>It can be used to represent additional information, such as unique identifiers. This can be used to differentiate return values from a series of function calls, all of which might be passed back through a specific register (e.g., x0). It can also be used for more explicit data parallelization, for example, to rely on explicit data stream propagation.
[0068] <metadata>Fields can be used to propagate additional information from the compiler or programmer. For example, this might indicate the expected evolution of a variable to enable value prediction at the receiving site.
[0069] Therefore, the example previously given in C can be converted to the following assembly (inserting send prompt and receive prompt instructions):
[0070]
[0071] In the example above, the send and receive instructions pass the value stored in register w20 (corresponding to variable d). As shown in the C code, variable d is passed between iterations of the loop. These two instructions also provide ".continuation" (e.g., the program counter value of .continuation) to disambiguate between nested loops (but disambiguation is unnecessary in this example). Therefore, the second microthread executing the second iteration of the loop will pause when it encounters a receive instruction until it receives notification that resource / register w20 is available. The first microthread executing the first iteration of the loop ignores receive instructions but will signal this availability when it encounters a send instruction associated with resource / register w20. After the first separation of the new parallel region, the first microthread can be identified as the microthread with the earliest epoch ID (the new parallel region is identified by its unique region ID == contiguous address). In practice, at the first separation, the microarchitecture knows there are no multiple thread activities (sequential mode), so identifying the microthread that will be responsible for handling iteration 0 is straightforward. This information can be stored in a flag for a specific microthread, so that the specific microthread knows it should ignore receive instructions.
[0072] Figure 7 The following illustrates how the above code can be executed. In the first microthread, the detach code is executed. This results in the creation of a second microthread using epoch ID 1. In this second microthread, the continuation code is executed, and i is immediately updated. The update function is not shown to reduce verbosity, but in this example, the update function will increment i (in register w19) by 1 according to the assembly code shown above. Then, a check is performed to see if i is less than n (1024). If so, the process proceeds to the detach instruction, where a third microthread (epoch ID = 2) is created. The second microthread then continues to the head and body of the ring. If i is greater than or equal to n, the second microthread runs the exit code, which causes synchronization between the microthreads.
[0073] At the body of the loop, the second microthread (epoch ID = 1) arrives at the receive instruction. This instruction cannot be executed (and therefore cannot be executed in any subsequent order) because a signal indicating that the resource ("d") is available has not yet been received.
[0074] Meanwhile, in the first microthread, after executing the detach instruction, the microthread continues to the body of the loop. After executing the complex_update function, it encounters a send instruction indicating that resource "d" is now available. The process of passing this message to the other microthreads is discussed in more detail below. Then, the first microthread enters the exit block.
[0075] Once the send instruction is executed in the first microthread, the receive instruction in the second microthread can be executed. This, in turn, eventually enables the send instruction of the second microthread to be executed, allowing the third microthread to progress beyond its receive instruction (and so on). Once the send instruction in the second microthread has been completed, a reattach instruction is executed, causing the second microthread to exit, as previously described.
[0076] This will be understood as following the model of microthread generation. Figure 4 The illustrated model. This technique, including the use of sending and receiving instructions, is also applicable to other execution models, such as those concerning... Figure 5 The example model.
[0077] Figure 8 An embodiment of a data processing apparatus for handling two micro-threads (small threads) is illustrated. Fetch and decode circuits 705a, 705b are provided for each of the small threads. These fetched and decoded instructions enter dispatch queues 710a, 710b, which store fetched and decoded instructions in program order (e.g.,). An instruction picker 735 picks the instruction to be executed from the dispatch queues 710a, 710b. The input operands for the selected instruction are stored in relation to each other in reservation stations 740a, 740b. Out-of-order execution of instructions is achieved by storing instruction input operands and monitoring the results generated by the execution pipeline for operand forwarding. Reservation stations are associated with execution units 745a, 745b (e.g., one reservation station per execution unit). Therefore, when operands for instructions become available in the reservation stations, they can be provided to the associated execution unit for execution.
[0078] Out-of-order execution can be achieved at each of the reserved stations via a renaming circuit. Like other components of System 700, the renaming circuit is replicated for each of the microthreads capable of concurrent execution. Therefore, architecture register files 715a and 715b are provided, which executor the non-speculated values of the architecture registers (e.g., the mapping of physical registers to architecture registers for instructions that have been successfully executed and committed in program order). In the event of pipeline flushing, the values of the ARF are restored. Reorder buffers 725a and 725b track the original program order of issued instructions and store the speculated result for each instruction. When an instruction is committed, the speculated result is propagated from the ROB entry to the designated register in the ARF. Within each ROB, the commit pointer points to the next entry (instruction) to be committed (e.g., in program order). Simultaneously, the issue pointer points to the next location in the ROB where the instruction will be added. Finally, register alias tables 720a and 720b indicate where the latest mapping of the architecture registers can be found. RAT entries may point to mappings in ARF 715a, 715b or entries in ROB 725a, 725b, depending on whether the instruction to write to the architecture register is committed. Error dependencies can be removed by creating a new entry in RAT 720a, 720b for each new value generated by the instruction. In this way, each new value generated by the instruction is stored in a new (physical) register.
[0079] Therefore, the instructions that exit execution circuits 745a and 745b are stored in the relevant ROBs 725a and 725b, depending on which microthread the instruction is executed for. RATs 720a and 720b will point to this instruction in the ROB until the instruction is committed. At this point, the RAT used for this register will point to the entry in the RAF, which provides a mapping from the architecture register to the physical register.
[0080] Only one microthread is allowed to be globally non-speculated. When synchronization instructions are executed by a microthread or a small thread and all other microthreads or small threads have executed reattach instructions, the architectural state of the small threads needs to be merged. For registers, this means merging the contents of the ARF: if a register has been written to by a small thread since its creation, the register holds the latest value for that particular epoch; otherwise, the register value for that epoch should be recursively collected from earlier microthreads. This behavior is achieved by adding a write bit to the entry in the ARF, which is set when the corresponding register is written. If multiple microthreads have thus written to the register, the "true" value of the register after reattachment will be the value stored in the last microthread that was written to the register. Obviously, if no microthread has written to the register, the value of the register remains unchanged.
[0081] Within this system, sending and receiving instructions utilize mailbox circuits 730a and 730b provided for each concurrently executing micro-thread or small thread. When a send instruction is encountered, it can only proceed if there are available entries in the mailboxes 720a and 730b of that micro-thread. If space is available, a new entry is added to the mailbox of that micro-thread when the send instruction completes. This entry includes a message ID indicating the resource involved in the send instruction. For example, if the resource is a register, this could be a register ID. The entry also includes a message type indicating the type of the resource. If the resource is a register, an optional register value field allows a register value to be specified, enabling efficient transmission of that register value. Finally, a validity entry can be used to indicate whether an entry in the mailbox is valid.
[0082] As an alternative to waiting for the send command to complete before adding the entry, the entry can also be added to the mailbox as part of the send command execution. In this case, additional metadata must be provided to track the speculative state of the send command and to respond appropriately in the event of erroneous speculatives. Part of the response to erroneous speculatives (e.g., after an incorrect branch in branch prediction) will involve invalidating the command across small threads. The link between the send and receive pairs can be stored as an additional field within the mailbox circuit so that commands executed due to erroneous send commands can also be invalidated.
[0083] When a receive instruction is encountered in a later (i.e., newer) small thread or microthread, the microthread or small thread stops until the entry corresponding to the expected source is marked as valid in the mailbox of the microthread that issued the receive instruction; that microthread is the direct ancestor of the microthread that issued the receive instruction. When the receive instruction completes, the mailbox entry of the send instruction that enabled the receive instruction to be dispatched (or issued) is invalidated.
[0084] Instead of each mailbox entry being associated with a single resource, a message ID field can also be associated with a group of resources. One way to do this is to implement the message ID field as a FIFO queue. This assumes that send commands are executed in program order. In this way, decoupling between microthreads / small threads can be increased, thereby further increasing parallelism.
[0085] It should be noted that the above system 700 is an example of how to handle multiple microthreads or small threads.
[0086] In the previous assembly code example, a hint instruction was explicitly provided in the form of a receive instruction. However, this is not necessary. Instead, the detach instruction itself can contain a hint that will provide the resource at a later time (e.g., in the detach instruction's metadata). For example:
[0087]
[0088] In such examples, the first instruction attempting to read the listed resource (w20) will stop. In this example, the instruction "mov w0,w20" will stop in the same way as described previously. The instruction will be permitted to be issued when the corresponding entry for w20 is found in the mailbox of the microthread in an earlier iteration.
[0089] In another variation, the receiving list is provided before the loop:
[0090]
[0091] send w20,.continuation
[0092] bl parallel_region(unsigned int)
[0093] reattach.continuation
[0094] In yet another variant, both the send and receive instructions can be removed, and operands can be added to instructions that make a resource available (e.g., perform a final write to a register) and request a resource (e.g., perform a first read from a register). For example:
[0095] .LBB14_1:
[0096] detach.continuation
[0097] mov w0,w19
[0098] bl parallel_region(unsigned int)
[0099] mov w1,w19
[0100] mov w0,w20.receive / / operand annotated to receive
[0101] bl complex_update(unsigned int,unsigned int)
[0102] mov w20.send,w0 / / operand annotated to send
[0103] bl parallel_region(unsigned int)
[0104] reattach.continuation
[0105] Encountering an instruction with a `.receive` operand means that the instruction will be paused until the requested resource (w20) becomes available, just like a receive instruction. Encountering an instruction with a `.send` operand means that the instruction indicates to the receiving microthread the availability of the specified resource (w20). In this variant, there is no indication of which loop it belongs to. Therefore, it is necessary to infer this information. For example, it can be assumed that such an indication applies to the outermost loop.
[0106] Previously, it was assumed in most cases that the resource in question was a register identified by a register ID. However, this is not always the case, and in practice, the availability of other resources (such as data values stored in memory or even blocks of code) can be indicated and the availability of those other resources can be awaited.
[0107] An alternative to providing dedicated mailboxes 730a and 730b as described above is for the ROB itself to act as the mailbox. In this case, it is necessary to record the link across microthreads (between send / receive pairs). Furthermore, send commands are prevented from being committed until the corresponding receive command has also been committed; otherwise, the register value will be lost from the ROB.
[0108] Figure 9 Examples of two other prompting instructions are shown, which can be used to indicate the availability of other resources (such as memory addresses or code blocks) (signaling) and the expectation of those other resources (waiting). Like... Figure 6 Similar to the illustrated prompts, these prompts permit (where microthreads are allowed to implement parallel execution) the propagation of resources identified by semaphore IDs and their values (if any) between microthreads (e.g., between loop iterations). When microthreading is not permitted, the prompts are simply ignored (e.g., decoded like NOP instructions).
[0109] <semaphoreid>The field is used to provide an identifier for each signal / wait pair, and thus can be used to identify a specific resource. A wait instruction for a specific identifier will wait until the corresponding signal instruction (which identifies the same identifier) is executed. In this example, the wait prevents any subsequent instructions from being executed until the wait is resolved. That is, the wait acts like a barrier, preventing subsequent instructions from executing in program order until the wait is complete. This can be achieved, for example, by setting a specific flag in the ROB entry. Therefore, semaphores can be used not only to "protect" variables but also for critical sections of code where only one microthread can execute at a time.
[0110] Like Figure 6 The instructions are the same as those shown. <regionid>The field is used to uniquely identify a loop or other data structure, and therefore can be used to disambiguate between the inner and outer loops.
[0111] Optional <epochdistance>The value can be used to indicate that the carried dependency is not between adjacent iterations, but between iterations (e.g., epochs) that are separated by a set distance (epoch distance). For example, in iteration n, a wait hint with an epoch distance of 4 would indicate that the signal with the matching semaphore ID that needs to be synchronized is in iteration n-4 instead of n-1. Similarly, if the epoch distance is 4 in a signaling instruction in iteration n, this would indicate that the corresponding wait instruction will be in a future iteration n+4. Thus, this can capture more complex memory dependencies, such as A[i+3] = A[i] + B[i]. In cases where a conflict is certain, an epoch distance of 0 can be used; this causes the current iteration to wait until all previous iterations have been signaled (or reattached).
[0112] Like Figure 6 The instructions are the same as those in the text, optional. <metadata>Fields can be used to transmit additional information from the compiler or programmer.
[0113] For example, consider the following code:
[0114]
[0115]
[0116] In this example, the variable "x" is used in the `read_modify_write` function call during most iterations. This causes the variable x to be read, modified, and then written back, thus (potentially) being used in the next iteration. Note that the function `frequently_true` returns true with a certain high probability, and therefore `read_modify_write` occurs with a certain high frequency. If `read_modify_write` does not occur frequently, the overhead associated with "protecting" the variable can be high, and this could be a condition upon which an ignorable hint is based. For example, resource monitoring could be used to detect this situation.
[0117] Therefore, the example previously given in C can be converted to the following assembly (inserting signal notification instructions and wait for notification instructions):
[0118]
[0119]
[0120] In the example above, the signaling and waiting instructions signal and wait on a semaphore with the ID tkn0 (corresponding to variable x). Both instructions also provide ".continuation" (e.g., the program counter value of .continuation) as a region ID to disambiguate the nested loop (but disambiguation is unnecessary in this example). Therefore, the second microthread executing the second iteration of the loop will pause when it encounters a wait instruction until it receives notification that the resource / variable tkn0 is available. The first microthread executing the first iteration of the loop will ignore the wait command (as the first microthread of the loop) and signal the availability of tkn0 when it encounters a signaling instruction associated with tkn0.
[0121] In practice, semaphore IDs are mapped to registers (or portions thereof). That is, wait and signal notification instructions use registers to create virtual dependencies.
[0122] This is about Figure 10 This diagram illustrates an example of an 8-bit register (tkn) used to support 8 semaphores. The "Signal" prompt instruction changes the corresponding semaphore in the tkn register (0 in this example) from 0 to 1, and the "Wait" prompt instruction does the opposite.
[0123] Figure 8 The illustrated mailboxes 730a and 730b can be used for semaphore enforcement. Here, in contrast to the register signaling illustrated previously, a special "type" is given for semaphore signaling, where a semaphore ID is given for the message ID instead of the register ID. Additionally, the epoch distance parameter is considered for its control.
[0124] Figure 11 The following illustrates how the above code can be executed. In the first microthread, the detach code is executed. This results in the creation of a second microthread using epoch ID 1. In this second microthread, the continuation code is executed, and i is immediately updated. The update function is not shown to reduce verbosity, but in this example, the update function will increment i (in register w19) by 1 according to the assembly code shown above. Then, a check is performed to see if i is less than n (1024). If so, the process proceeds to the detach instruction, where a third microthread (epoch ID = 2) is created. The second microthread then continues to the head and body of the ring. If i is greater than or equal to n, the second microthread runs the exit code, which causes synchronization between the microthreads.
[0125] At the body of the loop, the second microthread (epoch ID = 1) arrives at the waiting instruction. This instruction cannot be executed (and therefore cannot be executed in any subsequent order) because the available signal for x (protected by semaphore "tkn0") has not yet been received.
[0126] Meanwhile, in the first microthread, after executing the detach instruction, the microthread continues to the body of the loop (since it is the first microthread, wait instructions are ignored). Here, we will assume that the frequently_true function always returns true. Therefore, the next operation performed in the first microthread is a read_modify_write operation on the variable x. At this point, a semaphore instruction is encountered to indicate that the resource x protected by the semaphore "tkn0" is now available. This can be implemented using the mailboxes 730a and 730b described earlier. Then, the first microthread enters the exit block.
[0127] Once the signaling instruction is executed in the first microthread, the wait instruction in the second microthread can be executed. This, in turn, eventually allows the signaling instruction in the second microthread to be executed, which allows the third microthread to progress beyond its prompting instruction (and so on). Once the signaling instruction in the second microthread has been completed, a reattachment instruction is executed, causing the second microthread to exit, as previously described.
[0128] This will be understood as following the model of microthread generation. Figure 4 The illustrated model. This technique, including the use of signaling and waiting instructions, is also applicable to other execution models, such as those concerning... Figure 5 The example model.
[0129] Figure 12 Compiler 1200 is illustrated, which is an example of a data processing apparatus among the claimed data processing apparatuses. For example, the compiler could be a regular compiler or a just-in-time (JIT) compiler. The data processing apparatus could also be embodied as part of a pipeline. Within compiler 1200, input circuitry receives input code, which is processed by processing circuitry 1220 to produce output code, which is output by output circuitry 1230. The input code includes blocks of instructions (which may be identical). The output code corresponds to the input code but also includes previously mentioned hints indicating dependencies. In the case of the compiler, dependencies are more easily seen because the entire view of the code is viewed simultaneously. A simple way to do this is to find loops (e.g., for loops, while loops, or recursive function calls) where a particular variable is read before being written. In many cases, the nature of the (looped) code will imply RAW dependencies across iterations of the loop.
[0130] Figure 13A and Figure 13B This example illustrates the behavior of compiler 1200 regarding the placement of prompt instructions (in this case, in the form of wait and signaling instructions). Figure 13A In the for loop, the wait instruction is placed before the first instruction to read the protected resource (x), and the signal instruction is placed after the final instruction to write the protected resource (x). A small block of instructions 1300 exists within the for loop, not between the wait instruction and the signal instruction. These instructions preceding the wait instruction can be executed in parallel between microthreads. Figure 13B An alternative behavior is illustrated, where the previously described requirements are met, but the number of instructions between waiting for the instruction and signaling the instruction is minimized. Therefore, compared to... Figure 13A Compared to the previous example, the instruction block 1310, which can be executed in parallel, is expanded, resulting in greater achievable parallelism.
[0131] Figure 14 Another mechanism that can be used to handle dependencies is illustrated. This mechanism can be used as an alternative to the previously presented mechanism. Specifically, the ARF is extended with additional bit fields 1400 and 1410, which are used to indicate whether the first access to a particular register is a read (1) or not a read (0). If the first access to the register is a write, then a RAW dependency should not be possible. During reattachment, when the microthread is synchronized, a RAW dependency exists if the register has an asserted stale bit (1) and the same register is also written to by a previous microthread.
[0132] In cases where a previous messaging system is used, for example, using Figure 8 The illustrated mailboxes 730a and 730b can determine whether a message has been transmitted to indicate the availability of a resource (register). This can be achieved, for example, by disallowing the removal of entries from mailboxes 730a and 730b until reattachment occurs (assuming the validity bit of the entry has also been set to 0) or by using another tracking mechanism.
[0133] In cases where the previous message passing system is not used, no dependency mechanism has been provided, and therefore, the later (newer) small thread must be re-executed. This is because the value obtained for the register may be incorrect.
[0134] Figure 15 A pair of flowcharts 1500 and 1565 are shown to illustrate the behavior of compiler 1200 and data processing device 10, respectively. In this particular instance, it is assumed that no reference is used. Figure 14 The mechanism described.
[0135] In step 1505, the input code is received by compiler 1200. At step 1510, the input code is processed to produce output code. This process includes at least adding hints to the code. Then, at step 1515, the output code is output. The output code may be sequentially pipelined further down the pipeline (in which case compiler 1200 and device 10 are the same data processing device), or it may be output as an executable file to be executed later by device 10. In either case, at step 1520, the next instruction is executed by device 10. If, at step 1525, the instruction is a receive or wait instruction, then at step 1530, it is determined whether the specified resource has been indicated as available. If not, the execution of the instruction is suspended until the specified resource becomes available. Otherwise, at step 1535, the instruction is executed, and the process returns to step 1520. If, at step 1525, the instruction is not a receive or wait instruction, then at step 1540, it is determined whether the instruction is a send instruction or a signaling instruction. If yes, the specified resource is indicated as available at step 1545, and the process proceeds to step 1535. If the instruction is not a send / signal instruction, at step 1450, it is determined whether the instruction is protected. Specifically, it is determined whether the instruction is located between a send / receive pair or a signal / wait pair. If no, the instruction is executed at step 1535. Otherwise, at step 1555, it is determined whether the instruction is within a signal / wait block. If yes, the process waits at step 1560 until the resource becomes available, and then the process proceeds to step 1535. Otherwise, at step 1565, it is determined whether the instruction is performing a read of a protected register. If no, the process proceeds to step 1535. Otherwise, the process waits at step 1570 until the register becomes available, at which point the process proceeds to step 1535.
[0136] The concepts described herein may be embodied in computer-readable code used to manufacture devices embodying the described concepts. For example, the computer-readable code may be used in one or more stages of the semiconductor design and manufacturing process, including the electronic design automation (EDA) stage, to manufacture integrated circuits comprising devices embodying these concepts. The aforementioned computer-readable code may additionally or alternatively enable the definition, modeling, simulation, verification, and / or testing of devices embodying the concepts described herein.
[0137] For example, computer-readable code for manufacturing a device embodying the concepts described herein may be embodied in code that defines the hardware description language (HDL) representation of these concepts. For instance, the code may define a register-transfer level (RTL) abstraction of one or more logic circuits for defining a device embodying these concepts. The code may define an HDL representation of one or more logic circuits embodying the device using Verilog, SystemVerilog, Chisel, or VHDL (Very High Speed Integrated Circuit Hardware Description Language) and intermediate representations such as FIRRTL. Computer-readable code may provide definitions of the concepts or other behavioral representations of the concepts embodying the concepts using system-level modeling languages such as SystemC and SystemVerilog, which can be interpreted by a computer to enable simulation, functional and / or formal verification and testing of the concepts.
[0138] Additionally or alternatively, computer-readable code may define a low-level description of an integrated circuit component embodying the concepts described herein, such as one or more netlists or integrated circuit layout definitions, including representations such as GDSII. Other computer-readable representations of one or more netlists or integrated circuit components may be generated by applying one or more logic synthesis processes to the RTL representation to generate definitions for manufacturing devices embodying the present invention. Alternatively or additionally, one or more logic synthesis processes may generate a bitstream from the computer-readable code to be loaded into a field-programmable gate array (FPGA) to configure the FPGA to embody the described concepts. The FPGA may be deployed for the purpose of verifying and testing the concepts prior to manufacturing integrated circuits, or the FPGA may be deployed directly in a product.
[0139] Computer-readable code may include a mixture of code representations for manufacturing apparatus, such as one or more of RTL representations, netlist representations, or other computer-readable definitions used in the semiconductor design and manufacturing process for manufacturing apparatus embodying the present invention. Alternatively or additionally, the concept may be defined in a combination of computer-readable definitions used in the semiconductor design and manufacturing process for manufacturing apparatus and computer-readable code defining instructions that will be executed by the defined apparatus once manufactured.
[0140] Such computer-readable code can be contained in any known transient computer-readable medium (such as wired or wireless transmission of code over a network) or non-transitory computer-readable medium such as semiconductors, magnetic disks, or optical disks. Integrated circuits made using computer-readable code may include components such as one or more of the following: a central processing unit, a graphics processing unit, a neural processing unit, a digital signal processor, or other components that embody the concept individually or collectively.
[0141] In this application, the phrase "configured as..." is used to mean that the elements of the device have a configuration capable of performing the defined operation. In this context, "configuration" means the arrangement or manner of interconnection of hardware or software. For example, the device may have dedicated hardware that provides the defined operation, or a processor or other processing device may be programmed to perform the function. "Configured as" does not mean that the elements of the device need to be changed in any way to provide the defined operation.
[0142] While exemplary embodiments of the invention have been described in detail herein with reference to the accompanying drawings, it should be understood that the invention is not limited to those precise embodiments, and various changes, additions, and modifications can be made therein by those skilled in the art without departing from the scope and spirit of the invention as defined by the appended claims. For example, features of dependent claims can be combined with features of independent claims in various ways without departing from the scope of the invention.< / metadata> < / epochdistance> < / regionid> < / semaphoreid> < / metadata> < / messageid> < / regionid> < / registerid>
Claims
1. A data processing apparatus, the data processing apparatus comprising: A multi-threaded processing circuit is provided to execute processing operations of multiple micro-threads, each micro-thread operating in a corresponding execution context with a defined architectural state. and A decoder circuit that generates a first microthread for a first instruction block in response to the first occurrence of a split instruction, and generates a second microthread for a second instruction block in response to the second occurrence of the split instruction, wherein... The second instruction block includes data dependencies regarding the resources accessed in the first instruction block.
2. The data processing apparatus according to claim 1, wherein The first instruction block and the second instruction block are iterations of the same loop; and The data dependency extends iteratively across the loop.
3. The data processing apparatus according to any of the preceding claims, wherein The data dependency is a write-after-read data dependency on the resource.
4. The data processing apparatus according to any of the preceding claims, wherein The decoder circuit responds to: A first prompt instruction, configured to indicate the availability of the resource when executed in the first microthread, and A second prompt instruction is configured to indicate a request for the resource when executed in the second microthread.
5. The data processing apparatus according to claim 4, wherein The resources are one of the following: registers, variables, memory locations, and code blocks.
6. The data processing apparatus according to any one of claims 4 to 5, wherein Depending on whether the condition is met, the decoder circuit responds to the second prompt instruction by creating a virtual dependency; and Depending on whether the condition is met, the decoder circuit responds to the first prompt instruction by parsing the virtual dependency.
7. The data processing apparatus according to any claim 6, wherein The virtual dependency refers to the virtual dependency on the register.
8. The data processing apparatus according to claim 7, wherein The register in question is a physical register.
9. The data processing apparatus according to any one of claims 4 to 8, wherein the data processing apparatus comprises: Mailbox circuitry, configured to store resources that have become available, wherein The first prompt instruction is blocked from being issued until there is free capacity in the mailbox circuit; In response to issuing the first prompt instruction, a new entry is inserted into the mailbox circuit regarding the resource; The second prompt instruction cannot be issued until a corresponding entry for the resource exists in the mailbox circuit; and In response to the completion of the second prompt instruction, the corresponding entry for the resource is deleted from the mailbox circuit.
10. The data processing apparatus according to any one of claims 4 to 9, wherein The virtual dependency is resolvable only as a result of the execution of the first prompt instruction.
11. The data processing apparatus according to any one of claims 1 to 9, wherein The decoder circuit responds to a reattachment instruction in a specific microthread of the instruction to indicate the availability of each resource used by the specific microthread of the instruction to a newer microthread of the instruction, and to terminate the specific microthread of the instruction.
12. The data processing apparatus according to any one of claims 6 to 11, wherein If the condition is not met, the decoder circuit responds to the first prompt instruction and the second prompt instruction by generating a no-operation signal.
13. The data processing apparatus according to any one of claims 6 to 12, wherein The condition is whether the parallelization of the multiple microthreads is permitted.
14. The data processing apparatus according to any preceding claim, wherein the data processing apparatus comprises: A register checking circuit, configured to respond to obtaining an old register value by setting an old register flag; and The decoder circuitry determines whether the stale register flag is set in response to a reattachment instruction in a specific microthread of the instruction, and in response to setting the stale register flag, causes the specific microthread of the instruction to be re-executed.
15. A method, the method comprising: It executes processing operations in multiple micro-threads, each operating in a corresponding execution context with a defined architectural state; The first microthread is generated in response to the first occurrence of the detach instruction; as well as A second microthread is generated in response to the second occurrence of the separation instruction, wherein... The second instruction block includes data dependencies regarding the resources accessed in the first instruction block.
16. A non-transitory computer-readable medium for storing computer-readable code for manufacturing a data processing apparatus, the data processing apparatus comprising: A multi-threaded processing circuit is provided to execute processing operations of multiple micro-threads, each micro-thread operating in a corresponding execution context with a defined architectural state. and A decoder circuit that generates a first microthread for a first instruction block in response to the first occurrence of a split instruction, and generates a second microthread for a second instruction block in response to the second occurrence of the split instruction, wherein... The second instruction block includes data dependencies regarding the resources accessed in the first instruction block.
17. A data processing apparatus, the data processing apparatus comprising: An input circuit configured to receive input code including a first instruction block and a second instruction block; An output circuit configured to generate output code corresponding to the first instruction block and the second instruction block; and Processing circuitry, configured to generate the output code based on the input code, wherein The processing circuit is configured to generate: Within the output code, a first prompt instruction corresponding to the first instruction block is included. This first prompt instruction is configured to indicate resource availability. Within the output code, a second prompt instruction corresponds to the second instruction block, and the second prompt instruction is configured to indicate a request for the resource; and The second instruction block includes data dependencies regarding the resources accessed in the first instruction block.
18. The data processing apparatus according to claim 17, wherein The data dependency is in response to the read-after-write data dependency of the resource.
19. The data processing apparatus according to any one of claims 17 to 18, wherein The first instruction block and the second instruction block are iterations of the same loop; and The data dependency extends iteratively across the loop.
20. The data processing apparatus according to claim 19, wherein The processing circuit is configured to place the second prompt instruction before or at the first use of the resource within the body of the loop; and The processing circuitry is configured to place the first prompt instruction at or after the last use of the resource in the body of the loop.
21. The data processing apparatus according to claim 20, wherein The processing circuit is configured to place the second prompt instruction and the first prompt instruction such that at least a portion of the body of the loop is outside the area defined between the first prompt instruction and the second prompt instruction.
22. A method, the method comprising: Receive input codes including a first instruction block and a second instruction block; Generate output code corresponding to the first instruction block and the second instruction block; as well as The output code is generated based on the input code, wherein The output code includes: Within the output code, a first prompt instruction corresponding to the first instruction block is included. This first prompt instruction is configured to indicate resource availability. Within the output code, a second prompt instruction corresponds to the second instruction block, and the second prompt instruction is configured to indicate a request for the resource; and The second instruction block includes data dependencies regarding the resources accessed in the first instruction block.
23. A non-transitory computer-readable medium for storing computer-readable code for manufacturing a data processing apparatus, the data processing apparatus comprising: An input circuit configured to receive input code including a first instruction block and a second instruction block; An output circuit configured to generate output code corresponding to the first instruction block and the second instruction block; and Processing circuitry, configured to generate the output code based on the input code, wherein The processing circuit is configured to generate: Within the output code, a first prompt instruction corresponding to the first instruction block is included. This first prompt instruction is configured to indicate resource availability. Within the output code, a second prompt instruction corresponds to the second instruction block, and the second prompt instruction is configured to indicate a request for the resource; and The second instruction block includes data dependencies regarding the resources accessed in the first instruction block.