Hardware-optimized symmetric high-performance automated parallelization system with loop-level parallelization and method thereof

The compiler system addresses inefficiencies in multiprocessor code parallelization by partitioning code into compute block nodes and using matrices/tensors to optimize latency and parallelism, achieving improved throughput and hardware adaptation.

JP2026516776APending Publication Date: 2026-05-26マイナティックス アーゲー
View PDF 0 Cites 0 Cited by

Patent Information

Authority / Receiving Office
JP · JP
Patent Type
Applications
Current Assignee / Owner
マイナティックス アーゲー
Filing Date
2023-04-24
Publication Date
2026-05-26

AI Technical Summary

Technical Problem

Conventional compilers struggle to efficiently parallelize code for multiprocessor systems, particularly in managing latency and data dependencies, leading to suboptimal performance in modern computing architectures with increasing core counts and heterogeneous hardware.

Method used

A compiler system that automatically optimizes code for multiprocessor systems by partitioning it into compute block nodes, using matrices and tensors to minimize latency and maximize parallelism across multiple processing units, incorporating a parser, matrix builder, and optimizer to generate optimized machine code.

Benefits of technology

Enhances throughput by efficiently managing processor and data dependencies, optimizing low-level parallelism, and adapting to hardware-specific requirements, overcoming limitations of prior art systems.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure 2026516776000001_ABST
    Figure 2026516776000001_ABST
Patent Text Reader

Abstract

A symmetric automatic compiler system (1) and method for high-performance, hardware-optimized automatic parallelization of program code (3) for execution by a multicore or multiprocessor parallel processing system (2) having multiple processing units (21) that simultaneously process instructions for data in a parallel processing system (2) by executing program code (3). The automatic compiler system (1) converts the sequential source code (31) of program code (3) into parallel processing machine code (32) which includes several instructions that can be executed by multiple processing units (21) of the parallel processing system (2) or that control the operation of multiple processing units (21).
Need to check novelty before this filing date? Find Prior Art

Description

[Technical Field]

[0001] The present invention generally relates to multiprocessor systems, in particular to multicore systems and parallel computing systems that enable multiprocessing in which two or more processors or cores cooperate to execute multiple program codes and / or processor instruction sets simultaneously, wherein the multiprocessor system or parallel computing system comprises several central processing units linked to one another to enable multiprocessing or parallel processing to occur. In particular, the present invention relates to a compiler system that optimizes computer programs for execution by a parallel processing system having multiple processing units. More specifically, the embodiments described relate to a system and method for the automatic parallelization of code for execution in the described multiprocessor system. In the technical field of multiprocessor systems, important characteristics and classifications arise, among other things, depending on how processor memory access is handled and whether the system processors are of a single type or multiple types within the system architecture. [Background technology]

[0002] In recent years, fundamental changes have been observed in computer architecture, introducing unprecedented levels of parallelism that pose new challenges to traditional code optimization and parallelization techniques, impacting every aspect of data processing and operation in all electronic devices, from mobile phones to supercomputers. In particular, it creates computer and processor-specific technical requirements for code parallelization to achieve true optimization. While the traditional multi-core approaches (2, 4, and even 32 cores) adopted by the computing industry have gradually reached performance plateaus, technology is shifting towards many-core technology (hundreds and even thousands of cores) for higher performance per watt and per chip area. However, fully unlocking the potential of many-core approaches to ensure future advancements in sustained computing performance requires fundamental advancements in computer architecture and programming techniques that amount to a reinvention of computing. New technological trends in the microprocessor industry, as petaflop scales are achieved, will have a significant impact on the design of next-generation computing systems, especially so-called high-performance computing (HPC) systems. The need to shift to a geometric growth path in system concurrent parallelism is rethinking interconnect design, memory balancing, and I / O system design, which will have a dramatic impact on the design of future HPC applications and algorithms, particularly on the parallelization and architecture-specific adaptation of future applications and algorithms. The required redesign of existing application code is likely to be dramatic and technically challenging, similar to the transition from vector-based HPC systems to massively parallel processors (MPPs) that occurred in the 1990s. Given that such a comprehensive code redesign took almost a decade, there are serious concerns about making yet another large-scale migration in existing software infrastructure using conventional technologies.

[0003] One of the technical challenges and difficulties arises from various different technical fields, which suddenly face the technical objective of how to further optimize CPU design, system architecture, and programming models for future and current systems, taking into account the interconnection effects of new systems such as circuit design, computer architecture, embedded hardware / software, programming languages, compilers, and applied mathematics for HPC, as well as current constraints on device physics at the silicon level. If these technical challenges cannot be overcome by appropriate systems, particularly code optimization and parallelization systems, this even leads to the question of whether multi-core (or many-core) or multiprocessor systems are actually a reasonable response to the fundamental constraints on future IC design. The present invention makes it possible to solve the technical challenges of new optimization systems caused by these changes in the context of computer architecture, system architecture, and programming models for future computing systems, such as HPC systems.

[0004] Moore's Law, which still holds true (and is likely to hold true until 2023 according to the latest results), allows for the integration of twice the number of components into an integrated circuit every 18 months at a fixed cost. However, traditional sources of performance improvements, such as instruction-level parallelism (ILP) and clock frequency scaling, have flattened since 2003. In particular, processor performance improvements measured by SPEC benchmarks from 1975 to the present have improved by a remarkable 52 percent per year since 1986 (see, for example, JL Hennessy and D.A. Patterson, "Computer Architecture: A Quantitative Approach" (fourth edition, Morgan Kaufmann, San Francisco, 2006)). During that period, as process geometry scaled according to Moore's Law, the active capacitance of circuits was scaled down, resulting in manufacturers being able to keep the supply voltage constant, or even moderately lower, in order to increase clock speeds. This approach, known as "constant field" frequency scaling, has resulted in the continuous increase of CPU clock rates over the past 15 years. However, below the 90nm scale in silicon lithography, this technique began to reach its limits as static power losses due to leakage current began to outweigh dynamic power losses due to circuit switching. Power density is now the dominant constraint in the design of new processing elements, ultimately limiting the increase in clock frequencies of future microprocessors. The direct consequence of power constraints was the clock frequency stagnation, reflected in the flattening of performance growth rates that began in 2002. Since then, individual processor cores have been nearly three times slower than if progress had continued at the historical rate of the previous decade. Other approaches to extract more performance, such as instruction-level parallelism (ILP) and out-of-order instruction processing, have also resulted in diminishing returns.Having exhausted other well-understood means of extracting more performance from uniprocessors, the mainstream microprocessor industry has stalled further improvements in clock frequency and responded by increasing the number of cores on the chip. Estimates suggest that since then, the number of cores per chip has doubled every 18-24 months. Thus, to keep pace with the geometrically increasing waves of concurrent system parallelism that are causing a tsunami of parallelism, new kinds of parallelization systems and processor architecture-specific optimization programming structures are required. The industry's relatively simple response of clock frequency stagnation and doubling of core counts has led to the emergence of alternative approaches to computing, such as field-programmable gate arrays (FPGAs), graphics processing units (GPUs), or dataflow-like tile array architectures like TRIPS. The main obstacle to adapting such more radical approaches to hardware architectures is that, in the technical field, even less is known about how to efficiently program such devices for diverse applications than is known about parallel machines composed of multiple CPU cores.

[0005] Today, running a program in parallel on a multicore processor or multiprocessor system requires rewriting the code and manually or via tools adding OS parallelization primitives such as pthreads (POSIX Threads, known as pthreads, provides a parallel execution model structure that allows a program to control multiple different workflows that overlap in time. Each workflow is called a thread, and creation and control over these workflows are achieved by calling the POSIX Threads API. POSIX Threads is an API defined by the standard POSIX.1c, Threads extensions IEEE Std 1003.1c-1995). Even with high-level interfaces like OpenMP or MPI, parallelization is not an easy job for two reasons: (i) if the resulting code is not sufficiently synchronized, the computation is not deterministic, and (ii) if it is excessively synchronized, it is not sufficiently parallel. However, threads rely on a programming style that typically makes programs nondeterministic and constrains that nondeterminism to achieve deterministic objectives. Instead of manually parallelizing the code, those skilled in the art may rely on the compiler to automatically perform, for example, loop vectorization or loop parallelization. It should be noted that loop-level parallelization is one of the central aspects and technical challenges in HPC applications, as loop sections can introduce large computational demands. Opportunities to utilize parallel processing often arise in applications where data is stored in random-access data structures. However, even in simple examples, conventional compilers often cannot automatically parallelize. Furthermore, a second problem is the irregular code structure. Below, we will describe in detail how loops are parallelized by the system of the present invention using a just-in-time loop parallelization structure.

[0006] This introduces a third problem in parallelization: the memory organization of data. In the addition example, the array being added to is declared, for example, as a global variable. Therefore, when the computation is distributed, it becomes centralized. As a result, each thread retrieves the portion of the array it needs from the DRAM where it resides. Caches can help, but neighboring cores are slowed down by memory contention, and the cache miss rate is affected by the array's distribution. Furthermore, in programs that update shared data, complex hardware is required to keep the cache coherent, thereby slowing the average memory access time. Cache and memory hierarchies, as well as branch predictors, are hardware features that rely on the principle of locality, which is essentially based on the centralization of data (cache) and fetched code (predictor). When code and data are distributed, it is parallel locality that applies to the data. The principle of parallel locality states that consumers should be as close as possible to their producers. The system of the present invention also allows for optimizing the distance from producer to consumer for parallelized code, which is another way to quantify the quality of parallelization.

[0007] Conventional technologies have attempted to apply dataflow architectures separately to parallel computing frameworks and automated parallelization systems. A dataflow architecture is a dataflow-based computer architecture that directly contrasts with the traditional von Neumann architecture or controlflow architecture. However, a dataflow architecture lacks a program counter, and conceptually, the executionability and execution of instructions are determined solely by the availability of input arguments to the instructions; therefore, the order of instruction execution is unpredictable, i.e., the behavior is non-deterministic. Consequently, there is a need to provide an inherently deterministic dataflow architecture that enables automated parallelization compilers to manage complex technical tasks such as processor load balancing, synchronization, and access to shared resources by considering the underlying system architecture.

[0008] Generally, throughput can be improved when processing code is executed in parallel on a multi-core or multi-processor system. Multi-processor or multi-core systems (processors and cores are simply referred to as processors below for simplicity) involve breaking down code into smaller code blocks and efficiently managing code execution. For cores or processors to execute in parallel, data to each core or processor must be independent. Execution of instances of the same code block can be improved by running them simultaneously on several processors. Parallel processing efficiency can be reduced due to latency in data exchange between and / or between processor units when a processor requires data from another process performing a previous execution or currently performing a computation. Generally, when a processor enters a state where program execution is interrupted or not executed for any reason, and instructions belonging to it are neither fetched from memory nor executed, these states cause processor idle states that affect parallel processing efficiency. Data dependencies must be considered when scheduling processors. Efficiently managing multiple processors and data dependencies for higher throughput is challenging. It is desirable to have methods and systems for efficiently managing code blocks in computationally intensive applications. Latency problems also exist, for example, in single-processor systems where latency-oriented processor architectures are used to minimize the problem. It should be noted that these are microarchitectures of microprocessors designed to provide serial computing threads with low latency. These architectures generally aim to execute as many instructions as possible belonging to a single serial thread within a given time window, and the time required to execute a single instruction completely from fetch to retirement stage can vary from a few cycles to hundreds of cycles in some cases. However, these techniques do not automatically apply to the latency problems of (large-scale) parallel computing systems.

[0009] Therefore, parallel computing systems require efficient parallel coding or programming, and parallel programming becomes a programming paradigm. This involves, on the one hand, a method of dividing a computer program into individual sections that can run concurrently, and on the other hand, a method of synchronizing parallel code sections. This is in contrast to classical sequential (or serial) programming and coding. Parallel execution of a program can be supported on the hardware side, and programming languages ​​are usually adapted to this. For example, parallel programming can be done explicitly by having the programmer run parts of the program in separate processes or threads, or it can be done automatically so that causally independent (parallelable) instruction sequences run concurrently, i.e., in parallel. This parallelization can be done automatically by the compiler system if a computer with a multi-core processor or a parallel computer is available as the target platform. Some modern CPUs also recognize such independence (in the machine code or microcode of a program) and can distribute instructions to different parts of the processor so that the instructions run concurrently (out-of-order execution). However, as soon as individual processes or threads communicate with each other, they influence each other, so in that sense they are no longer concurrent as a whole, and only the individual subprocesses remain concurrent with each other. If the execution order of communication points for individual processes or threads cannot be defined accordingly, races can occur, particularly deadlocks where two processes wait for (or block) each other, or race conditions where two processes overwrite each other's results. Conventional techniques use synchronization techniques, such as mutual exclusion (Mutex) techniques, to solve this problem. While such techniques can prevent race conditions, they do not automatically enable optimized parallel processing of processes or threads with minimal latency for processor units.A (micro)processor is based on an integrated circuit that enables arithmetic and logical operations based on two binary values ​​(most simply 1 / 0). For this purpose, the binary values ​​must be available to the processor's compute unit. The processor unit needs to obtain two binary values ​​to compute the result of the expression a=b operand c. The time it takes to retrieve the data for these operations is known as latency. These latencies have a wide hierarchical range from registers, L1 cache, memory access, I / O operations, or network transfers, as well as processor configuration (e.g., CPU vs. GPU). Since every single component has latency, the overall latency for compute is primarily the combination of hardware components required to retrieve data from one place to another in modern computing infrastructure. In modern architectures, different software layers (e.g., operating systems) also have a significant impact. The difference between the fastest and slowest place for the CPU (or GPU) to retrieve data can be very large (10). 9 (More than double). Figure 1 illustrates the formation of latency in modern computing infrastructure. As shown in Figure 1, parallel computing machines with different distinct architectures are being developed. It is important to note that parallel architectures enhance traditional computer architecture concepts with communication architectures. Computer architecture defines important abstractions and organizational structures (such as user-system boundaries and hardware-software boundaries), while communication architecture defines fundamental communication and synchronization behaviors. This also addresses organizational structures.

[0010] Computer applications are typically written in the highest level, i.e., a high-level language, based on the corresponding programming model. Various parallel programming models are known, such as (i) shared address space, (ii) message passing, or (iii) data-parallel programming that references the corresponding multiprocessor system architecture. A shared-memory multiprocessor is a parallel machine of this class. Shared-memory multiprocessor systems provide better throughput for multiprogramming workloads and support parallel programming. In this case, the computer system allows a set of processors and I / O controllers to access a set of memory modules through some hardware interconnect. Memory capacity is increased by adding memory modules, and I / O capacity is increased by adding devices to I / O controllers or by adding additional I / O controllers. Processing power can be increased by implementing faster processors or by adding more processors. As shown in Figure 2, resources are organized around a central memory bus. Through the bus access mechanism, any processor can access any physical address in the system. Since all processors are assumed to be equidistant from all memory locations, or are actually equidistant, the access time or latency for all processors on the memory location is the same. This is called a symmetric multiprocessor system.

[0011] The message-passing architecture is another class of parallel machine and programming models. It provides inter-processor communication as explicit I / O operations. Communication is combined at the I / O level, rather than at the memory system level. In the message-passing architecture, user communication is performed by using operating system or library calls that perform lower-level actions, including the actual communication operations. As a result, there is a distance between the programming model and the communication operations at the physical hardware level. Sending and receiving are the most common user-level communication operations in a message-passing system. Sending specifies the local data buffer (to be sent) and the receiving remote processor. Receiving specifies the sending process and the local data buffer where the sent data will be placed. In the send operation, an identifier or tag is attached to the message, and the receive operation specifies matching rules, such as a specific tag from a specific processor or any tag from any processor. The combination of sending and matching receiving completes inter-memory replication. Each end specifies its local data address and pairwise synchronization event. Message passing and shared address spaces traditionally represent two distinct programming models, each with its own paradigm regarding sharing, synchronization, and communication; however, today, the fundamental machine architectures are converging toward a common organization.

[0012] Finally, data parallelism is a further class of parallel machines and programming models, also known as processor arrays, data parallel architectures, or single-instruction multiple data machines. The main feature of this programming model is the ability to perform operations in parallel on each element of a large, regular data structure (such as an array or matrix). Data parallel programming languages ​​are typically implemented by treating the local address space of a process group, usually one per processor, as forming an explicit global space. Since all processors communicate with each other and there is a global view of all operations, either a shared address space or message passing can be used. However, developing programming models alone cannot increase the efficiency of a computer, nor can developing hardware alone. Furthermore, top-level programming models inevitably introduce boundary conditions, such as model-specific architectures, given by the programming model requirements. Since parallel programs consist of one or more threads operating on data, the underlying parallel programming model defines what data a thread needs, what operations it can perform on the required data, and in what order those operations proceed. Therefore, due to the boundaries of the underlying programming model, there are limitations to optimizing machine code in multiprocessor systems. Parallel programs must always coordinate the activity of their threads to ensure that dependencies between programs are enforced.

[0013] As Figure 1 shows, parallel computing machines are developed using different and distinct architectures, each resulting in different latency configurations in their computing infrastructure. One of the most common multiprocessor systems is the shared-memory multiprocessor system. Essentially, three basic architectures are known for shared-memory multiprocessor systems: (i) Uniform Memory Access (UMA), (ii) Non-uniform Memory Access (NUMA), and (iii) Cache Only Memory Architecture (COMA). In the UMA architecture (see Figure 3), all processors uniformly share physical memory. All processors have equal access times for all memory words. Each processor may have private cache memory. The same rules apply to peripherals. When all processors have equal access to all peripherals, the system is called a symmetric multiprocessor. When only one or a few processors can access peripherals, the system is called an asymmetric multiprocessor. In the NUMA multiprocessor architecture (see Figure 4), access times vary depending on the location of the memory word. Shared memory is physically distributed among all processors and is called local memory. The collection of all local memories forms a global address space accessible to all processors. Finally, the COMA multiprocessor architecture (see Figure 5) is a special case of the NUMA multiprocessor architecture. In the COMA multiprocessor architecture, all distributed main memory is converted into cache memory. The COMA architecture can also be applied to distributed memory multicomputers. A distributed memory multicomputer system consists of multiple computers, usually called nodes, interconnected by a message-passing network. Each node functions as an autonomous computer with a processor, local memory, and sometimes I / O devices.In this case, all local memory is private and accessible only to the local processor; therefore, such a machine is also called a no-remote-memory-access (NORMA) machine. Other known multiprocessor architectures include, for example, multi-vector computers and single-instruction multiple-data (SIMD) parallel computers, parallel random-access machines (PRAM) and parallel computers based on very large-scale integrated (VLSI) chips, all of which have different multiprocessor architectures and infrastructure characteristics. In short, different multiprocessor architectures cause different forms of latency in their computing infrastructure, so the efficiency of a computer cannot be increased by developing programming models alone, nor by developing hardware alone.

[0014] As mentioned, if a computer with a multicore processor or a parallel computer is available as the target platform, the compiler system can also perform code parallelization automatically. This type of automatic parallelization, also called auto-parallelization, refers to the conversion of sequential code into multi-threaded and / or vectorized code to use multiple processors simultaneously, for example, on a shared-memory multiprocessor (SMP) machine. In conventional systems, fully automatic parallelization of sequential programs is technically difficult because it requires complex program analysis and the best approach may depend on parameter values ​​unknown at compile time. The programming control structure that compiler systems focus on most is loops, because typically most of a program's execution time takes place within some form of loop. There are two main approaches to loop parallelization: pipelining multithreading and cyclic multithreading. Compiler structures for automatic parallelization typically include a parser, analyzer, scheduler, and code generator. The compiler system's parser, for example, covers the first processing stage where a scanner reads the input source file and identifies all static and external usages. Each line in the file is checked against a predefined pattern to separate it into tokens. These tokens are stored in a file later used by the grammar engine. The grammar engine checks for token patterns that match predefined rules to identify variables, loops, control statements, functions, etc., in the code. In the second stage, the analyzer identifies sections of code that can be executed simultaneously. The analyzer uses static data information provided by the scanner-parser. The analyzer first detects all completely independent functions and marks them as individual tasks. Then, the analyzer finds which tasks have dependencies.In the third stage, the scheduler lists all tasks and their interdependencies in terms of runtime and start time. The scheduler generates an optimal schedule in terms of the number of processors to be used or the total execution time of the application. In the fourth and final stage, the scheduler generates a list of all tasks and details of the core on which each task will run, along with the time each task will run. The code generator then inserts special configurations into the code that will be read during execution by the scheduler. These configurations instruct the scheduler on which core a particular task will run on, along with its start and end times.

[0015] When a cyclic multithreading parallelizing compiler is used, the compiler attempts to divide each loop so that each iteration can run concurrently on a separate processor. During automatic parallelization, the compiler typically performs two passes of automated evaluation before actual parallelization to determine two fundamental prerequisites for parallelization: (i) whether the loop is safe to parallelize based on dependency analysis and alias analysis, and (ii) whether it is worth parallelizing based on program workload and estimation (modeling) of the capacity of the parallel system. The compiler's first pass performs a data dependency analysis of the loop to determine whether each iteration of the loop can run independently of the others. Data dependencies can sometimes be addressed, but may incur additional overhead in the form of message passing, shared memory synchronization, or some other method of processor communication. The second pass attempts to justify the parallelization effort by comparing the theoretical execution time of the parallelized code to the sequential execution time of the code. It is important to understand that code does not always benefit from parallel execution. The extra overhead that may be associated with using multiple processors can undermine the potential speed improvements of parallelized code.

[0016] When a pipelined multithreading parallel compiler is used for automatic parallelization, the compiler attempts to break down a sequence of actions within a loop into a series of code blocks, each of which can be executed simultaneously on a separate processor.

[0017] Many parallel problems with relatively independent blocks of code like this exist, especially in systems that use pipes and filters. For example, when producing a live broadcast, many different tasks must be executed multiple times per second.

[0018] A pipelined, multithreaded, parallel compiler attempts to assign each of these operations to different processors, usually arranged in a systolic array, and to insert appropriate code to transfer the output of one processor to the next. For example, in modern computer systems, one focus is on using the capabilities of GPUs and multi-core systems to compute such independent blocks of code (or independent iterations of loops) at runtime. The accessed memory (directly or indirectly) is then marked for different iterations of the loop and can be compared for dependency detection. Using this information, iterations are grouped into levels so that iterations belonging to the same level can be executed independently and in parallel.

[0019] In the prior art, many compilers exist for automatic parallelization. However, most modern prior art compilers for automatic parallelization rely on the use of Fortran as a high-level language, meaning they are only applicable to Fortran programs because Fortran provides stronger guarantees regarding aliasing than languages ​​like C. Typical examples of such prior art compilers are (i) Paradigm compiler, (ii) Polaris compiler, (iii) Rice Fortran D compiler, (iv) SUIF compiler, and (v) Vienna Fortran compiler. Further drawbacks of automatic parallelization by prior art compilers include (a) difficulty in analyzing dependencies in code using indirect addressing, pointers, recursion, or indirect function calls because dependencies are difficult to detect at compile time, (b) loops often have iterations of unknowns, (c) access to global resources is difficult to coordinate with respect to memory allocation, I / O, and shared variables, and (d) it is often difficult to achieve a high level of optimization of the code because irregular algorithms using input-dependent indirection hinder compile-time analysis and optimization.

[0020] One of the key tasks of a compiler is to efficiently handle latency. Compilation is the transcription from a so-called high-level language (such as C, Python, or Java®) that is human-readable into assembler / processor code, which consists only of instructions available on a given processor. As already explained, modern applications with high data or computational demands must target appropriate infrastructure, introducing many different latency issues, only some of which are currently solvable by traditional compiler optimization techniques.

[0021] For all levels of complexity (hardware components), solutions have historically been developed and evolved, ranging from compiler optimization techniques to multithreaded libraries for concurrent data structures to prevent race conditions, code vectorization, GPU systems with corresponding programming languages ​​(e.g., OpenCL (Open Computing Language)), frameworks like TensorFlow for distributing computations by programmers, and big data algorithms like MapReduce, which is a programming technique and associated implementation for processing and generating big datasets using parallel distributed algorithms on a cluster. In the field of high-performance computing, techniques ranging from theoretical, mathematics-based techniques for partitioning large matrices to special gridding techniques for finite difference or element methods have been developed and defined. This includes protocols, for example, in cluster infrastructure, the Message Passing Interface (MPI) supports the transfer of data to different processes across the infrastructure.

[0022] As mentioned above, the list of conventional optimization techniques is long. However, from a systems theory perspective, the problem is more or less always the same: how can code (any code) interact most efficiently with latency in a complex hardware infrastructure? Compilers work well when using a single CPU. As soon as hardware complexity increases, compilers are no longer really able to parallelize the code. Parallelization simply becomes an approximation of the CPU, for example, by introducing microprocesses. The hardware industry regarding CPUs, GPUs, and their clusters is primarily focused on those specific areas, and developers and researchers have focused on implementation techniques and framework development, and so far have not ventured into the field of more general (cross-industry) approaches. Furthermore, authors Martino Ruggiero, Alessio Guerri, Davide Bertozzi, Michela Milano, and Luca Benini published a method for partitioning algorithms that process data streams across different processor cores in their publication "A Fast and Accurate Technique for Mapping Parallel Applications on Stream-Oriented MPSoC Platforms with Communication Awareness" (International Journal of Parallel Programming, Vol. 36, No. 1, Feb 08). The authors' model is a simple communication network with a simple and additive communication model between processor cores. This does not allow for realistic conclusions regarding the actual communication load caused by partitioning across multiple cores.

[0023] Generally, known processor manufacturers focus on their own processors and associated hardware components, while other developers, such as high-performance computing (HPC) research groups, focus on the use of numerical methods and libraries. Currently, there are no attempts to solve problems related to compiler system optimization from a theoretical perspective of the system by accessing the latency dynamics arising from a given source code. Source code in the prior art simply consists of a series of statements that directly read from and write to a given target infrastructure.

[0024] The prior art document, M. Kandemir et al., "Slicing Based Code Parallelization for Minimizing Inter-processor Communication" (2009 International conference on compilers, architecture, and synthesis for embedded systems (cases '09), Grenoble, France, October 11-16, 2009, p. 87-96), discloses a system for automatic parallelization aimed at minimizing inter-processor communication in a distributed memory multicore architecture by applying the concept of iterative space slicing; that is, this prior art system is based on an iterative approach. The disclosed system does this by iteratively determining the partitioning of other arrays in the application code, i.e., by partitioning the output array by iteratively determining the array parts, and information is iteratively retrieved from previously sliced ​​array parts. In code parallelism, slicing refers to the process of extracting statements from a program that have a potential impact on a specific statement of interest, and this is the slicing criterion (see, for example, J. Krinke, "Advanced slicing of sequential and concurrent programs," (20th IEEE International Conference on Software Maintenance, 2004. Proceedings., 2004, pp. 464-468)).These slicing techniques are used in conventional systems that rely on point data / control dependencies (see, for example, JL Hennessy and D.A. Patterson, "Computer Architecture" (Fifth Edition: A Quantitative Approach, The Morgan Kaufmann Series in Computer Architecture and Design, fifth edition, p. 150ff)) and in data flow analysis (see, for example, Gary A. Kildall, "A unified approach to global program optimization" (proceedings of the 1. stThis exhibits a similar effect to that described in the annual ACM SIGACT-SIGPLAN symposium on Principles of programming languages ​​(POPL '73). Association for Computing Machinery, New York, 1973, USA, 194-206). By using iterative space slicing, these systems can evaluate which iterations of which statements affect the values ​​of a given set of elements from a particular array A. Thus, iteratively, the system can return a set of loop operations to be assigned to processor p, for example, from a loop nest s, by relying on a particular set of data elements accessed by processor p from array A. Furthermore, the prior art document Fonseca A. "Automatic Parallelization: Execution Sequential Programs on a Task-Based Parallel Runtime" (International Journal of Parallel Programming, April 2016) discloses another system for automatically parallelizing sequential code for use in multicore architectures. The system discloses using data groups and memory layouts and then checking dependencies based on task parallelism. Therefore, in order to automatically parallelize a program, the system needs to analyze the accessed memory and evaluate possible dependencies between parts of the program. For example, in the example of automatically parallelizing code to generate the Fibonacci sequence, the disclosed system evaluates that, for a small number of inputs, the cost of creating a new task is higher than the cost of running the method. This evaluation is then used as the primary requirement for determining the task's position during the automatic generation of parallelized code, and this evaluation is performed by a specific function that relies on a set of seven requirements to find the best position.Finally, this function outputs so-called hard dependencies, which are instructions that can subsequently introduce tasks, and so-called soft dependencies, which give the current task a set of already defined tasks that it must wait for to execute. Parallelization is completed when all tasks have been instantiated with a specified location, and tasks are marked for execution by waiting for the current task to execute and reading their results. Finally, U.S. Patent Application Publication 2008 / 0263530 discloses a system for translating application code into optimized application code, or executable code suitable for execution on a computing architecture including at least first and second levels of data memory units. When scheduling instructions, the principle of locality, also known as locality of reference, is used. This relates to the phenomenon where the same value or associated memory location is accessed frequently. Different types of locality of reference should be distinguished. In temporal locality, a resource referenced at one point in time is likely to be referenced again soon after. In spatial locality, the likelihood of referencing a memory location is greater if a nearby memory location has been recently referenced. Programs and systems exhibiting locality exhibit predictable behavior and therefore provide code designers with opportunities to improve performance through code and data prefetching, pre-computation, and caching for future use. In this type of data evaluation optimization, the disclosed system accesses locality before layout locality, thereby consolidating accesses temporally as much as possible for frequently accessed data when data transfer operations occur, and consolidating accesses spatially as much as possible for sequentially accessed data. Thus, in the first process (access locality), partial fixing occurs and a range of options is given. In the second process (layout locality), one option is selected from a predefined range. This selection of one option may be based on a cost function.As a variation of one embodiment, the system also addresses the problems of parallel data transfer and memory retrieval by focusing on the portion of application code that has data parallel loops. The transformation structure makes it possible to address both data-level aspects of different levels of memory units, such as background memory, foreground memory, registers, and on functional units.

[0025] In short, while parallel compilers exist, they typically focus on independent levels of parallelism, such as instruction-level parallelism (ILP) targeting VLIW (Very Long Instruction Word) and EPIC (Explicitly Parallel Instruction Computing) architectures, data and vector parallelism such as high-performance Fortran and MMX / SSE-enabled compilers, or thread-level parallelism (TLP) in the case of compilers supporting the OpenMP API or PGI accelerator compilers for GPUs. Even more sophisticated architecture-centric approaches like IBM's Octopiler still require manual performance tuning, and therefore, the entire software development process must be manually adapted to the new prerequisites. Nested hierarchical memory systems, combined with all kinds of multi-level parallelism, finer granularity, and software-managed or user-managed data transfer, must be utilized and represented by algorithms. In addition, applications must be designed with scalability across several processor generations and concepts in mind. Comprehensive hardware knowledge is required to achieve optimal throughput at every step of the application mapping (e.g., in numerical simulations). There are complex trade-offs between implementation performance, productivity, portability, and flexibility. The systems and methods of the present invention approach hardware-aware computing by providing the best combination of schemes, parallel algorithms, and platform-specific implementations for a given source code of an application.

[0026] Furthermore, current programming approaches to conventional automated parallelization systems and multicore systems, particularly heterogeneous parallel systems, unfortunately do not meet the specific needs of such systems. While high-level parallel programming models provide the abstract view required by today's complex applications, they lack fine-grained control over hardware mapping, resulting in reduced efficiency in hardware resource utilization. Strict hardware-aware approaches enable such fine-grained control, but they focus on hardware mapping. The systems and methods of the present invention, based on a hybrid approach, offer a novel technical combination of both aspects.

[0027] As will be further explained below, conventional parallel programming approaches can be divided into three fields: shared memory, message passing, and data parallelism, each with its own corresponding standardized programming environment. Examples (in order of mention) include OpenMP (Open Multi-Processing), which targets the compiler-available Task Parallel Library (TPL); MPI (Message Passing Interface), which addresses manually utilized thread-level and pipelined parallelism; and High-Performance Fortran, intended for compiler-assisted use of data parallelism (DP). These programming models support only minimal flexibility and typically do not allow for fine-grained architecture mapping. Of these three, message passing offers the highest level of control over application architecture mapping. However, it has the drawback of forcing programmers to perform detailed partitioning and orchestration. Furthermore, one of its biggest drawbacks is that hardware heterogeneity is usually not represented by any of these models, as it is outside the scope of the problem. A certain degree of flexibility, allowing for dynamic changes in the number of threads created, is supported by OpenMP. Partitioned Global Address Space (PGAS) is a programming interface that defines a global address space on potentially distributed systems, focusing on leveraging locality of reference, where a portion of the shared memory space may have affinity to a particular thread. Examples of this model include Unified Parallel C and Co-array Fortran, as well as more recent industry-leading approaches such as Chapel (Cray) and X10 (IBM).

[0028] In particular, heterogeneous platforms require fine-grained methods to adapt application code to a given platform at the lowest hardware level. One example of a conventional technique is Cell BE, which forces programmers to explicitly partition programs into individual chunks that run on a single vector processing unit (SPE). Communication must be explicitly formulated using so-called direct memory access streams, allowing individual SPEs to fetch the necessary data and write the resulting data back. This careful matching of computation and communication can lead to orders of magnitude faster results compared to simpler implementations. However, this is a very cumbersome, error-prone, and time-consuming task. Conventional homogeneous multicore platforms also require hardware-aware programming techniques to minimize communication overhead, for example, through data locality optimization and proper prefetching. This becomes more pronounced in current and future multicore architectures, as such architectures feature separate schemes of cache sharing and interconnection techniques.

[0029] Another problem with all the conventional approaches described is the need for an additional runtime layer and often language-centric extensions. Furthermore, they do not consider application requirements such as real-time requirements or computational precision. Different conventional approaches are based on carefully extending the existing system layer. However, they are inherently language-independent, operating system-independent, and incompatible with existing parallel programming models. Moreover, overhead only appears for triggered options such as performance measurement and feature profiling for guided execution, and profiling overhead is still often about an order of magnitude lower than required.

[0030] To achieve true hardware-optimized parallelism, every part of the application code must conform to multi-level parallel units, hierarchical and potentially nested memory subsystems, and heterogeneous components of computing units. All aspects must be explicitly represented in the implementation, and conventional techniques offer little software support or mechanisms to facilitate automatic and optimized resource utilization and hide hardware details without impacting performance. Hardware heterogeneity is increasing, yet the algorithms used and their representation within applications remain inadequate. Current programming techniques primarily rely on a minimally invasive approach where local parts of the application are identified for acceleration and offloaded to specific computing engines. For overall benefit, additional communication through narrow bottlenecks must be taken into account. However, conventional solutions are often isolated and not portable. Hardware-specific optimization techniques include computational arrangement (vectorization, loop unrolling, sorting, branch removal, etc.), data structure optimization (array access patterns, memory alignment, data coalescing), and data transfer optimization (blocking of spatial and temporal locality, caching and cache bypass, in-place algorithms). This is because managing the parameter space is becoming increasingly difficult, and therefore a parameter space should be included. In known prior art systems, there is no way to avoid an autotuner that searches for the (Pareto) optimal setting of implementation parameters. For selected kernels, autotuning may yield results, but usually at the cost of a lack of platform portability. [Overview of the project]

[0031] One object of the present invention is to provide a compiler system for multiprocessor and multicomputer systems that optimizes the latency of processing units in a multiprocessor system, compiles program code into machine code, thereby efficiently managing multiple processor and data dependencies for higher throughput, and without the drawbacks of the prior art systems described above. Specifically, an object of the present invention is to provide a system and technique that can be used to achieve the best performance in a multiprocessor machine through automatic parallelization, thereby optimizing the utilization of low-level parallelism (temporal and spatial) at the level of machine instruction processing. A further object of the present invention is to overcome the drawbacks of prior art techniques that are typically limited to handling parallelization sections that are constrained by specific systems, such as loops or particular sections of code. The automatic parallelization system should be able to optimize the identification of parallelization opportunities as critical steps while generating multithreaded applications.

[0032] According to the present invention, these objectives are achieved, in particular, by the features of the independent claims. In addition, further advantageous embodiments can be derived from the dependent claims and related descriptions.

[0033] According to the present invention, the above objectives of a symmetric automatic compiler system and corresponding method for hardware-optimized automatic parallelization of program code executed by a multicore or multiprocessor parallel processing system having multiple processing units that simultaneously process instructions for data within a parallel processing system by executing program code are achieved, in particular the automatic compiler system comprises means for converting sequential source code of program code written in a programming language into parallel processing machine code containing several instructions executable by multiple processing units of the parallel processing system, or for controlling the operation of multiple processing units, wherein the parallel processing system comprises a memory unit including at least a main execution memory unit including multiple memory banks for holding data of at least a portion of the processing code, and a transition buffer unit including a high-speed memory for storing the starting position of the processing code and a data segment containing at least a branch instruction or jump instruction and / or memory references and data values ​​used, wherein the main execution memory unit is a transition buffer The compiler system provides slower access times than a single unit, and the execution of processing code by the parallel processing system involves latency, which is given by the idle time of the processing unit between the processing unit sending back data after processing a particular block of instructions in the processing code for the data and the processing unit receiving the data necessary to execute a consecutive block of instructions in the processing code, and the compiler system includes a parser module for translating sequential source code into code having a flow of basic instructions executable by the processing unit, the basic instructions being selectable from a limited set of basic instructions specific to the processing unit, the basic instructions including, for the processing unit, exclusively basic arithmetic and logical operations and / or basic control and memory operations, the parser module includes means for partitioning the code of basic instructions into compute block nodes, each compute block node consisting of the smallest possible segmentation of a sequence of basic instructions of code that can be processed by a single processing unit that cannot be further decomposed, and the smallest possible segmentation of basic instructions is,Characterized by a sequence of basic instructions framed by consecutive read and write instructions, the sequence is indestructible by smaller sequences of basic instructions between consecutive read and write instructions, the read and write instructions are necessary for a processing unit to receive the data required to process the sequence of basic instructions and to send the data back after processing by the sequence, the compiler system includes a matrix builder for generating matrices from a computation chain separated from the code, the matrices include a computation matrix, a transfer matrix and a task matrix, each column in the computation matrix includes computation block nodes that can be processed simultaneously based on the feasibility of read and write instructions that transfer the data required to process the computation block node, the transfer matrix includes transfer and processing properties for each computation block node, the transfer and processing properties include at least the data size of the data to be sent and the identification of the source computation block node and target computation block node of the data transfer, a certain computation block node Characterizing at least the data transfer properties from a node to a successive compute block node and / or processing characteristics relating to one of a plurality of processing units, where a task is formed by a matrix builder, and in the case of a compute block node, each associated with different reads, the tasks of the task matrix are formed by dividing the compute block nodes of the columns of the compute matrix equally according to the number of plurality of symmetric processing units, forming one task for each of the plurality of processing units for each column of the compute matrix, and dividing the remaining compute block nodes into at least a portion of tasks based on a predefined scheme, where a compute block node has reads to which at least partially identical data is transferred, the tasks are formed by minimizing the number of reads uniformly or essentially uniformly across processing units, and / or by minimizing the integrated processing time uniformly across each of the processing units if it exceeds a predefined offset value, and the compiler system, based on the compute chain given by the optimized task matrix,The compiler system includes a code generator for generating parallel processing machine code for multiple processing units having optimized total latency. Additionally, the compiler system may include an optimizer module that uses matrix optimization techniques to minimize total latency by, for example, providing an optimized structure of tasks in a task matrix, where each column of the task matrix forms a computation chain of one or more tasks that create an ordered flow of computation block nodes to be executed by one of the multiple processing units. When matrices or tensors are used, the optimization using the optimizer module may be based, for example, on numerical matrix optimization techniques (or more general numerical tensor optimization techniques). Technically, the optimization problem can be formulated using tensors and / or matrices, thus obtaining a matrix / tensor field optimization problem. For linear optimization, for example, the optimizer module can use matrices and linear programming. In certain applications of the present invention, the concept of tensors may be technically beneficial, for example. In optimization, tensor techniques can solve systems of nonlinear relations and equations, and for unconstrained optimizations, the second derivative is used. The tensor method can be used as a general-purpose method, particularly for problems where the Jacobian matrix in the solution is singular or a bad condition. The tensor method can also be used for linear optimization problems. A key feature of tensors is that their values ​​do not change even when they undergo regular nonlinear coordinate transformations; therefore, this concept can be technically useful for characterizing structural properties that do not depend on regular nonlinear coordinate transformations. Thus, tensor optimization can also be applied within the framework of nonlinear optimization. However, it should be noted that one of the technical advantages of the present invention is that all known matrices are linear optimization approaches, in contrast to prior art optimization techniques in the field of automatic parallelization of source code, whereas prior art systems must rely primarily on nonlinear optimization. Optimization, as used herein,This describes the problem of finding a set of inputs to an objective function that yields the maximum or minimum function evaluation. For this technically challenging problem, various machine learning algorithms can be used with an optimizer module, ranging from fitting logistic regression models to training artificial neural networks. When the optimizer module is implemented by an implemented machine learning structure, it can typically be formulated as provided using continuous function optimization, where the input arguments to the function are real-valued numbers, e.g., floating-point values. The output from this function is also a real-valued evaluation of the input values. However, as a variation of the embodiment, one can also use an optimization function that takes discrete variables, i.e., provides a combinatorial optimization problem. To technically select the best optimization structure, one approach, for example, might be to group the selectable optimization structures based on the amount of information available about the target function to be optimized, which can be used and utilized by the optimization algorithm. It is clear that the more information available about the target function, the easier it becomes to optimize that function by machine learning, depending certainly on the fact that the available information can be effectively used in the optimization. Therefore, one selection criterion can be associated with a differentiable target function by asking, for example, whether it is possible to calculate the first derivative (gradient or slope) of the function for a given candidate solution. This criterion partitions the available machine learning structures into those that can utilize the calculated gradient information and those that do not, i.e., machine learning structures that use derivative information and machine learning structures that do not. Where a differentiable objective function can be used, it should be noted that, in this specification, a differentiable function refers to a function that can generate a derivative for any given point in the input space. The derivative of a function with respect to a certain value is the rate of change or amount of change of the function at that point, and is also called the slope. The first derivative is defined as the slope or rate of change of the objective function at a given point, and the derivative of a function with two or more input variables (e.g., multivariate input) is called the gradient. Therefore, the gradient is,The derivative can be defined as the derivative of a multivariate continuous objective function. The derivative of a multivariate objective function is a vector, and each element of the vector is called a partial derivative, i.e., the rate of change of a given variable at that point, assuming all other variables are kept constant. Furthermore, partial derivatives can be defined as elements of the derivative of the multivariate objective function. Then, the derivative of the derivative of the objective function, i.e., the rate of change of the rate of change of the objective function, can be generated. This is called the second derivative. Thus, the second derivative can be defined as the rate at which the derivative of the objective function changes. In this case, for a function that takes multiple input variables, this is a matrix, called the Hessian matrix, and the Hessian matrix is ​​defined as the second derivative of a function with two or more input variables. Simple differentiable functions can be analytically optimized using known calculus. However, the objective function may not be solvable analytically. The optimization used can be significantly easier if the gradient of the objective function can be generated. Gradient information can be used, and some machine learning structures that may be used in this application include bracketing algorithms, local descent algorithms, first-order algorithms, and second-order algorithms.

[0034] The present invention has, among other advantages, the ability to provide and achieve large-scale optimization based on the lowest possible code structure and to reduce high-level programming language code to a small number of basic instructions, which cannot be reduced any further with respect to their data input and output points because the machine instruction set that can be executed on a CPU / microprocessor is limited. Basic instructions include, for example, (i) arithmetic operations such as +, -, *, / , and in numerical applications, i.e., mathematical operations such as integration or differential analysis are reduced to these basic instructions, (ii) logical operations such as AND, OR, (iii) declaration of variables and arrays, (iv) comparison operations such as same, greater than, less than, (v) code flow such as jumps and calls, (vi) if (condition) {codeA} else {codeB}, and (vii) loop (condition). The interaction between modern high-level languages ​​(e.g., Python, C, Java®, etc.) and the limited resources of processor instructions can be analyzed and made accessible by creating a "mapping" of the reading and writing of "data points" by their operation. In other words, by mapping the read and write interactions of a single instruction using a suitable representation that can also be represented graphically, they can be made available for numerical optimization techniques, thereby automatically parallelizing the source code and obtaining always-executable concurrent code. Several approaches exist for accessing these interactions, but none of them map the read and write patterns of the source code to data introduced by the programmer's choice of variable definitions, and then extract the necessary sequential chains to introduce potential communication patterns, thereby not "mapping" the code to a wide range of hardware infrastructure. This method discloses a novel approach to "adapting" source code to a given hardware infrastructure across all levels (FPGA, CPU, GPU, cluster, etc.).

[0035] The present invention further has the advantage that the disclosed method and system can solve known technical problems, such as solving nested loops dealing with arrays used to solve PDEs (partial differential equations) from a new perspective, or known problems that occur in the optimization steps of SOTA compilers. The method gives a new perspective to the code, and this new scope is based on the physical effects that occur in all classical computing infrastructures, resulting in a general method for mapping computations to a given hardware structure and deriving parallel representations of the code on given hardware, or on hardware ideal for a given code. This is based on preserving all "read" and "write" dependencies of the introduced data nodes and constructing instruction chains according to these dependencies. By extracting these instruction chains, the minimum bit size for computing the instruction chain of the target platform is extracted. Since all instruction chains can be represented as combinational circuits (where the output depends only on the current input), these sets of instructions represent combinational circuit blocks. Instruction chains within the same sequence can be processed in parallel, limited only by delays caused by physical properties, i.e., the limits of binary computation (the delay between applying a voltage and obtaining a stable result).

[0036] The resulting computational block nodes and their flow graphs return a qualified base in the matrix, resulting in a general method for re-examining code applicable to different computing units (e.g., CPU, GPU, FPGA, microcontroller, etc.). This method offers a new perspective on the interaction between ICT software and hardware, following the principles of systems theory. This provides a method that can bring novel solutions in a wide range of fields, as follows: (a) Adaptive Hardware - FPGA (Field Programmable Gate Array) / ACID (Atomicity, Consistency, Isolation, Durability): The present invention decomposes code into chains of instructions that clearly represent the logical elements of an integrated circuit. This method provides a general form for optimizing combinations of computation and communication, and can be used to optimize groups of instructions based on the same "bit-pattern" / "signal", for example, to automatically optimize the transfer of software to an FPGA, or to bring a new approach to bridging the gap from code to chip floor planning. (b) ML (Machine Learning) / AI (Artificial Intelligence): Machine learning and artificial intelligence code require many resources, especially during the training phase. This method can be used, for example, (i) to optimize known code, (ii) to support code development that adapts complexity during runtime and is therefore difficult to parallelize beforehand (because this method always results in optimized code), and (iii) to support future approaches that are not neural network-based (e.g., genetic algorithms, see, for example, R. Farber, "Inside HPC Special Report, AI-HPC is Happening Now"). (c) High Performance Computing (HPC) applications: This method can be used to translate code from, for example, Python to C code using the MPI support library, thus bridging gaps in different research fields (e.g., development from HPC to AI). Another application could be the implementation of adaptive mesh refinement used in numerical modeling software packages for engineering applications, weather forecasting models, etc. Alternatively, it can be used to combine models with different spatial and temporal resolutions (e.g., computational fluid dynamics models and agent-based models) to improve existing software packages in different fields, such as modeling and analysis software packages. (d) Automated business processes: The present invention can also be used for process management, where the decision of whether a unit should work on a task or send it to another unit is a well-known problem. The present method provides an approach to this problem. (e) Cloud, desktop operating systems, virtual machines, and general deployments: Having a common approach available to "reduce" the code regarding basic required behavior and possible parallel options supports a wide range of solutions in the interface between software and hardware. This interface obviously arises, in particular, for any form of operating system, software virtualization and / or deployment, or more specifically, for virtualization solutions for cloud infrastructure, for example, operating systems (with multi-core systems), virtual machines to support a mix of different operating systems, or similar examples. (f) Heterogeneous Platforms, (i) IoT and Edge Computing: Governing a given situation in different fields, such as IoT projects, autonomous driving, combined mobile and cloud applications, and other forms of applications running with and / or on mixed hardware infrastructure. The method can be adapted to determine how to optimally distribute data, computation, and / or data communications on the platform. Furthermore, it can be incorporated into the process of deploying / developing software for different properties of hardware components of a given network of computing units, and the code can be optimized to satisfy target properties, for example, by reducing latency in some parts of the software system. (g) Embedded systems: Embedded systems have high requirements for power consumption or other specific adaptations to a given code, such as having only a reduced instruction set on some microprocessors or similar challenges. This method can directly support this mapping because it can be optimized for given physical properties, and therefore the most efficient code representation can be obtained for any given code. (h) Self-optimizing algorithms: The present invention enables a fully autonomous circle, meaning that the algorithm can optimize itself on a given platform without any manual interaction. This opens up new applications and fields that were previously unknown. [Brief explanation of the drawing]

[0037] The present invention will be described in more detail, by example, with reference to the drawings. [Figure 1]A diagram schematically illustrates the formation of latency under different modern computing infrastructures. A (micro)processor is based on an integrated circuit that enables arithmetic and logical operations based on two binary values. For this purpose, the binary values ​​must be available to the processor's compute unit. The processor unit needs to obtain two binary values ​​in order to compute the result of the equation a=b operand c. The time it takes to retrieve the data for these operations is known as latency. These latencies from registers, L1 cache, memory access, I / O operations, or network transfers, as well as processor configurations (e.g., CPU vs. GPU), have a wide hierarchical range. Since every single component has latency, the overall latency for compute is primarily the combination of hardware components required to retrieve data from one place to another in modern computing infrastructure. [Figure 2] This block diagram schematically illustrates a shared-memory multiprocessor as a class of parallel machines, which forms the basis of the shared-address programming model as top-level parallel programming. In a shared-memory multiprocessor architecture, it is assumed that in this computer system, a set of processors and I / O controllers can access a set of memory modules through a certain hardware interconnect. Memory capacity is increased by adding memory modules, and I / O capacity is increased by adding devices to I / O controllers or by adding additional I / O controllers. Processing power can be increased by waiting for faster processors to become available or by adding more processors. All resources are organized around a central memory bus. Through the bus access mechanism, any processor can access any physical address in the system. Since all processors are assumed to be equidistant from all memory locations, or are actually equidistant, the access time or latency for all processors on memory locations is the same. This is called a symmetric multiprocessor. [Figure 3] A block diagram illustrating the UMA architecture is shown. In the UMA architecture, all processors share physical memory uniformly. All processors have equal access time for all memory words. Each processor may have private cache memory. The same rules apply to peripherals. When all processors have equal access to all peripherals, the system is called a symmetric multiprocessor. When only one or a few processors can access peripherals, the system is called an asymmetric multiprocessor. [Figure 4] A block diagram illustrating the NUMA multiprocessor architecture is shown. In the NUMA multiprocessor architecture, access time varies depending on the location of the memory word. Shared memory is physically distributed among all processors and is called local memory. The collection of all local memories forms a global address space accessible to all processors. [Figure 5] A block diagram illustrating the COMA multiprocessor architecture is shown. The COMA multiprocessor architecture is an exception to the NUMA multiprocessor architecture in which all distributed main memory is converted into cache memory. [Figure 6] As a schematic example, a block diagram is shown illustrating the different scopes of the unit "basic block" (or "block unit") and "computation block node". In use in this application, a "computation block node" is essentially different from a block unit used in a SOTA (State-Of-The-Art) compiler. [Figure 7]A simplified but more realistic block diagram is shown, illustrating that the method of the present invention takes advantage of the fact that logarithmic instructions (e.g., FYL2X on a modern CPU) take much longer than floating-point addition and / or multiplication instructions (e.g., FADD, FMUL). The method of the present invention adds the statements "x:=a+b" and "y:=a*b" to two different computation block nodes (cbn) because both are based on the same information "a" and "b". The "log2(x)" statement is appended to "x=a+b" because it uses the information "x". Since the information "y" is transferred, the information is available to both independent computation chains. [Figure 8] Figure 7 shows an example of how the code can be divided into machine code executable on two compute units synchronized by any form of IPC (note that IPC means communication between two compute units rather than "InterProcessCommunication"). This matrix shows the clock cycles required to compute different machine instructions as an example of how to obtain the time values ​​for computing instructions. In this form, in Figure 8, we can see that unit 2 computes the long-running instruction "log2(x)" and unit 1 processes the loop while incrementing a ("a=a+1") (see Figure 7). [Figure 9]A block diagram schematically illustrates the method of the present invention, which forms two matrices, referred to herein as “numerical matrices,” from the flow graph of compute block nodes (note that “numerical” can also, as a variation, refer to text data in certain cases, since all data on IT infrastructure can be understood at a low level as numerical, e.g., binary). One contains the instruction chain, and the other contains the possible transfer properties (between other compute block nodes). Thus, the code extracted from the matrices always forms the pattern “Compute -> Communicate,” as will be seen in detail in the following sections. Naturally, when the code is mapped to a single unit, the communicating portion disappears (and the computation (= chain of instructions) is aggregated), and the method of the present invention is reduced to an approach using “basic blocks,” which can also be processed by a state-of-the-art compiler. Furthermore, matrices, which represent a form far more scalable than graphs in accessing information, each demonstrate the qualified properties of a control flow graph. The definition of a compute block node (cbn) also illustrates the general properties of the matrices of the present invention: in one matrix, each row has an independent flow of instructions (=computations), and in the other matrix, there are the necessary transfers (=communications) to other cbns. As a result, this ensures that a) no further information is needed to compute all instructions within a compute block node; b) the information used is not changed anywhere else in the same compute step throughout the code; and c) only information unaffected by the computation during this time step can be transferred. [Figure 10] Each row of the compute matrix and transfer matrix together shows a block diagram that schematically illustrates how combinations of instruction and communication entry chains for a single unit. The units depend on the implementation level (e.g., bare assembly, thread, process, compute node, etc.). Naturally, empty compute cells or unused communication entries (empty cells in the compute and / or transfer matrices) disappear, and the start and end communication links also disappear along with them, as seen in Figure 10. [Figure 11]A block diagram schematically illustrates one possible optimization by the system of the present invention, which provides optimized ideal hardware for technical computation and processing problems. The most obvious method for such optimization is by constructing different combinations of rows from the computation matrix and the transfer matrix, each combination being one possible new parallel / concurrent code (as transfers on the same unit disappear and computations are aggregated), and then evaluating its properties on the target infrastructure, as shown in Figure 11 for a simple example. [Figure 12] A block diagram schematically illustrates an exemplary multiprocessor system 2 having two or more processing units 21 (multiple processors), each sharing main memory 22 / 221 / 222 / 223 and peripheral devices 25, in order to process program code 3 simultaneously. [Figure 13] A block diagram schematically illustrates a modified example of an exemplary embodiment of the present invention, in which source code 31 is used as input code to an automated parallelization compiler system 1 comprising a parser 11, a computational blockchain module 14, a matrix builder 15, an optimizer 16, and a code generator 17, wherein the automated parallelization compiler system 1 generates a parallelized and optimized target code 32 as machine or assembler code for execution by a parallel processing system 2 having a plurality of processing units 21. [Figure 14] A block diagram schematically illustrates an exemplary compiler system known from prior art systems, in comparison to the automatic parallelization compiler system 1 of the present invention. [Figure 15]Block diagrams are shown schematically illustrating exemplary basic elements for tree structures and / or computation graphs. Computations are reduced to one type of statement: result=param1 operation param2. Numerical operands are +, -, *, / and only these from a numerical standpoint. Within source code 31 as a high-level language, values ​​are assigned to variables in the form variablename=value. This is a link to a "virtual" location (in variablename) for storing the value. Source code 31 is usually sequential, which is the way a programmer thinks. According to the present invention, the code is a different approach in which the code is viewed as savelocation1=savelocation2 operation savelocation3. Based on this, for example, a basic graph or tree structure element is introduced having two input data nodes 33 / 331 / 3311 (datanodein1 and datanodein2), an operation node 332, and output data nodes 33 / 332 / 3312 (datanodeout). They are connected by directed edges, as seen in Figure 15. As used herein, a node 33 is a basic unit of a data structure, such as a sequence of linked processor instructions (a compute block node 333 / operation node 332) or a tree data structure as a data input or data output structure (datanodein / datanodeout). A node 33 contains data and can be linked to other nodes 33. Links between nodes 33 are often given by pointers (arrows) in the graph of Figure 15. [Figure 16]A block diagram schematically illustrates the exemplary basic elements of the source code. In the lexer and parser 11, operations from higher languages ​​are reduced to basic graph or tree structure elements. Thus, it becomes possible to use: (i) arithmetic operations, i.e., +, -, *, / ; (ii) logical expressions such as conditions, i.e., a==b or a>=b or similar that lead to true or false outputs; (iii) variable assignment name=value; (iv) flow control operations as branch expressions such as (1) if (condition) {block1} and (2) loop expressions such as loop (condition: incremental variable: maxvalue for incremental variable) {block1}. Herein lies an analogy to the basic operations of assembler code, which is the instruction set in processor 21, typically having three parameters. The statements and basic graph elements describe two reads (datanodein13311 and datanodein23312) and one write access (datanodeout3312) after an operation (operation node 332). Multiple assignments to a variable name create versions of this variable, resulting in different data nodes 331. [Figure 17] This shows how each version builds a new data node 331. [Figure 18] A block diagram schematically illustrates an exemplary sequence of simple operations 332 in a tree structure or graph. Each statement can add a sequence of program code 31 to the tree structure or graph. Complex expressions are reduced to a series of expressions of the type result=param1 operand param2 (due to the need to reduce the computation on a binary computing system to such a form). When an operation node 332 accesses a data node 331 that another operation node 332 is writing to, the construction of the sequence begins by connecting these operation nodes 332 with directed edges (next edges). [Figure 19]This method demonstrates the mapping of writes and reads in a tree structure or graph for all data nodes 331. As a rule to simplify the following steps, only one write is allowed to data node 331 (this helps to simplify the operation on the graph later). Otherwise, a new operation 332 is introduced to model multiple writes to data node 331. [Figure 20] A block diagram schematically illustrates how Δtreadwrite35 / 351 describes the time between write and read access to data node 331. In this interpretation, the latency Δtreadwrite351 can be seen as a numerical value representing the time that data node 331 must be transferred to another process in the multi-processing system 2. The interpretation of Δtreadwrite351 depends on the level of hardware setup. It is the technical and physical time between write access 3311 (I / O process, network card, etc.) and read access. Δtreadwrite351 is a unit given by the hardware infrastructure. Δtreadwrite351 may consist of different Δt: Δttotal = Δt1 + Δt2 + Δt3 + Δtn (e.g., L1 - cache access - memory access). 1 - In the case of dependencies (one operating node reads from one dependent data node), Δtreadwrite351 is given, and each must be very short. 2 - Note that other issues arise when dependencies exist. This will be explained below. [Figure 21]Block diagrams are shown to schematically illustrate exemplary dependencies between basic tree structure elements and graph elements. As a variation, it becomes easier if a rule is set that only one operation node 332 writes to one data node 331. Thus, the situations in which a new operation node 332 is added in the sequence are different but finite. That is, (i) 0 - dependency: placement: independent, (ii) 1 - dependency: placement: after the dependent operation node 332, (iii) 2 - dependency: unknown. Therefore, Δtreadwrite 351 for both data nodes 331 (in13311 and in23312) depends on the history of their preceding operation nodes 332. At this point, in order to find Δtreadwrite 351, the history of all preceding Δtreadwrite 351 for datanode in13311 and datanode in23311 must be known. This history of Δtreadwrite 351 must be placed in comparison to Δtlatency 352. This is the time required to deliver information or data points to another location via System 2. [Figure 22]A block diagram is provided to schematically illustrate how data / information can be considered, for example, whether it is possible to transfer data from one process to another, or in the case of threading, for example, whether it is possible to prevent simultaneous writes. The movement of data can be considered, for example, as a basic operation (operation K), and the transfer is the length of Δtlatency 35. It is important to note that the interpretation of Δtlatency 35 is highly dependent on the hardware system and can be seen as the time for transferring data / information through the system. Furthermore, the number of operational nodes unaffected by the transfer during this time can be calculated, if the system allows it, for example, in the case of direct memory access (DMA) network transfers. Or, in the case of a multithreaded system 2 (where two or more processes access the same data but a serious race condition occurs), this Δtlatency 35 can be considered a block time where one process reads / writes the corresponding data while other processes are not allowed. A transmission (see Figure 23) can be seen as transferring information or data from a source to a target location through system 2. Transmission is not yet a clearly defined pattern (e.g., send and receive), and it is unclear whether it will be required or not in the final code. This can only be done after optimization for the corresponding platform / hardware infrastructure. [Figure 23]A block diagram schematically illustrating exemplary compute block nodes 332 / CB1, CB2, ..., CBx is shown. A compute block node 333 may be introduced as follows: (i) a compute block node 333 consists of connected operation nodes 332, (ii) operation nodes 332 constitute one chain 34, (iii) a compute block node 333 may be connected to the next compute block node 333 or control flow node 334, e.g., branch node 3341, (iv) Δtcomputation 352 is the time to compute all operation nodes 332 (representing instructions) within the compute block node 333, (v) this has a minimum length Δtlatency 35. During this time, it is possible to transfer data within the computing infrastructure, and (vii) to describe the communication, a transmission consisting of the following is introduced: (a) Source: location within computing block node 333 (start, end), computing block node 333id, operation node id, datanodein1 / datanodein23311 or output data node 3312, (b) Target: location within computing block node 333 (start, end), computing block node 333id, operation node 332id, datanodein1 / datanodein23311 or output data node 3312. Transmission does not involve explicitly sending or receiving information -> Computation block node 333 can begin transmitting and / or receiving data information at the start and end of block 333 (before and after all operational nodes 332 have been computed) -> This model is typically applied to explicit non-blocking transmit / receive communication schemes (e.g., Message Passing Interface (MPI)), where transmission and reception can occur independently of computation (e.g., by Direct Memory Access (DMA) network cards). However, block transmit and receive function similarly by explicitly introducing operational nodes that have transmit and receive operations (and have their own Δtreadwrite 351).If communication is not permitted, for example in a multithreaded approach (where threads share the same data, but only time dependencies can be guaranteed by a locking mechanism), sending and writing may be interpreted as setting and releasing locks, and Δtlatency351 must be interpreted accordingly. [Figure 24] A block diagram schematically illustrates the exemplary processing of program flow control elements in a tree structure or graph. The condition node 335 is realized on the basis that (i) each condition within an if condition or loop condition creates a new "level", e.g., cond:0->cond:1, (ii) each condition knows how many levels are given between its own level in the program and the base level (condition 0) (e.g., cond:0->cond:1->cond:2, meaning that two conditions have been computed up to this point in the code), and (iii) the condition node 335 is connected by a directed edge to branch nodes 334 / 3341 having the same condition. Furthermore, branch nodes 3341 are introduced, where (i) each condition has at least one branch node 3341, and (ii) each branch node 3341 is connected to a compute block node 333 belonging to this branch (code in the if clause section). Conditions are generated by operation nodes 332 having (logical) expressions with "conditional" results such as true or false. Introducing conditions is one way to determine which compute block node can be assigned a new operation in the "fastest" way (the compute block nodes must be in the same condition level group, but may be in different branch nodes). Note that branch nodes do not correspond to blocks within branches in the definition of "base blocks". [Figure 25]This block diagram schematically illustrates the exemplary processing of an "if statement". An if statement branches the code under one condition (if (condition) {codeA}). As a result of a logical conditional expression that needs to be transferred within the system, -> a subsequent empty compute block node 333 is added after the compute block node 333 of the operation node 332, which contains the logical command -> this is the time required to transfer the result of the comparison (i.e., the condition) to another process -> it may be used to compute something else -> this compute block node 333 may be marked as a branch send type (CB2). After this, two directed edges of CB2 333 are added to a new branch node with a new compute block node for the code in branch1 and a so-called hidden branch node (see below) that is used when the condition is not met (however, it is not an else clause, but it may be). The result of the conditional expression must be transferred to the subsequent branch -> a send package is added to the end of CB1. Edges from branch nodes and hidden branch node 3342 can only be set after parsing all statements within the branch code section, and therefore only after the closing statement of the if condition (see below). [Figure 26] A block diagram schematically illustrates the handling of an exemplary nested "if statement". Since each statement in the code is added to the graph in the order in which it is read, the control edge connection between branch node 3341 and subsequent branch node 3341 can only be made after reaching the end mark of the if statement -> nested if statement. The correct condition node 335 with the correct branch node 3342 can be found by calculating the last condition level (which is reduced by the ending if statement) and traversing the graph to the correct node 33. [Figure 27]A block diagram illustrating the exemplary processing of a "loop statement" is shown. Note that, as with the branching described above for if statements, loop statements can be handled by several adaptations. In this example, a loop statement leads to a branch in the code as long as one condition is met by incrementing a variable until a specific value is reached ((loop (condition, i, 2) {codeA})). This is the same as in the case of an if statement, and adds CB4 333 for a transmission with type loopbranch-transmission. An increment operation node 332 is added to the variable defined in the expression. The result of the condition expression must be forwarded to the subsequent branch -> a transmission package is added to the end of CB3 333. Edges from branch node 3341 (branch1) after loopbranch node 3343 (branch2) and from compute block node 333 with type transmission can only be set after reaching the end statement of the loop statement (see below). [Figure 28] A block diagram schematically illustrates the exemplary processing of nested loop statements. Since each statement in the code is added to the graph in the order in which it is read, the control edge connection between the compute block node 333 with the loop branch send type and the subsequent branch node 3341 can only be made after the loop statement -> end mark of the nested loop statement is reached. This can be done by finding a lower condition level based on the last added statement and finding the correct loop branch send node 33. The compute block node 333 with the compare and increment operation node 332, as well as the compute block node 333 of type loop branch send, must be reconnected to the branch node 3341 of the previous loop. The branch node connections after the loop must also be updated.

number

number

number

number

number

number

[0038] Definition of Terms (i) "Computation block node" The definition of the term “computation block node,” which groups instructions and involves communication / transfer data to other computation block nodes, is important to this application. The term “computation block node” as used herein does not have a commonly recognized meaning, but it differs from similar terms used in the latest technology.

[0039] The well-known basic block (see, e.g., Proceedings of a symposium on Compiler optimization; July 1970, Pages 1-19, https: / / doi.org / 10.1145 / 800028.808479) is the central definition in classical control flow graphs (CFGs). In simplified terms, they group statements that do not contain jumps or jump targets internally. Therefore, given inputs, they can execute their operations uninterruptedly to the end, i.e., to the output. This is a fundamental concept in modern compilers. The definition of the basic block is also historically focused on a single computational unit and is very well established. Optimization methods exist for a wide range of problems, and how they solve different technical problems has been demonstrated. However, when we look at code aimed at splitting statements into different dependent units (e.g., connected via a shared cache, a bus, or a network), this definition lacks granularity and the classical scope hinders a broader perspective. By scoping blocks based on arbitrary unique information given within the code (viewing the information as a bit pattern), and combining this scope with the time associated with the computation and transfer of information within the system, a different but good physically based perspective is created for a given code. Alternative scoping enables new options and solves several well-known technical problems in today's state-of-the-art compilers (see the following examples regarding PDE, Fibonacci, or pointer ambiguity).

[0040] The term “computation block node” as used in this application is based on the interrelationship of transfer and computation time for a given set of statements, which is not applied in this way in SOTA compilers. These newly defined “computation block nodes” group instructions that use the same information that is not modified by any other instructions (statements) in any other computation block node during a given time in the complete code. In this way, they group instructions that can be processed or computed independently of any other statements using a scope based on the information (information as a distinct bit pattern), which is referred to in this application as an “indivisible instruction chain”. Each of these chains of instructions in every computation block node has a physical-based “time” associated with the time it takes for a unit to process or compute them on given hardware. Since hardware properties have a fundamental impact on the time required to process or compute instructions (as do software components such as the OS and drivers), “computation block nodes” also correlate them to the time required for the possible transfer of any other information to another “computation block node” in the complete code during a given time (if required during a particular program step). Each "computation block node" knows what information for its own instructions must be exchanged (communicated / transferred, i.e., "received" or "transmitted") with other "computation block nodes" and when. Thus, the "computation block nodes" used in this application bring a new scope and decision criterion, which represents one of the central aspects of code parallelism, in relation to computing information (bit patterns) on a unit or transferring this information to another unit and computing it in parallel. This decision can only be made if it is guaranteed that the information used will not change during any particular program step (or time) in any other part of the program.Furthermore, constructing block nodes with this scope not only offers advantages in parallelizing a given code, but this scope also offers several advantages for problems that are not adequately addressed by state-of-the-art compiler optimization techniques. Such problems and different solutions are documented, for example, in the publication D. Grune, "Modern compiler design." To demonstrate the technical advantages, some of the benefits arising from using the new scope for some of these known technical problems are shown below, such as the improved performance for pointer ambiguity and Fibonacci series code, and how this method solves previously unsolvable problems such as PDE parallelization.

[0041] First, different scopes are illustrated in the schematic example in Figure 6. This figure has been adapted to more easily illustrate what the system and method of the present invention does, for example, that the statement "y>a" does not occur twice within the same computation chain, and that the resulting "computation" -> "communication" model leads to the corresponding placement of loops, jumps, or flow control instructions. Nevertheless, this example illustrates what different scopes of computation block nodes give compared to the base block, namely that "a" and "b" do not change in block 1, and the information of the condition "y>a" is already known after the evaluation of the statement "y:=a*b", and the alternative scopes of computation block nodes take these properties into account. The proposed perspective of computation block nodes groups statements in a new way. This shift in perspective arises from an approach of grouping actions that depend on information that does not change at the same time step in the code. In this example, it is shown that two independent computation chains develop, both independent with respect to the information of "y".

[0042] In the simplified but more realistic example in Figure 7, the method of the present invention takes advantage of the fact that logarithmic instructions (FYL2X as an example on a modern CPU) take much longer than floating-point addition and / or multiplication instructions (e.g., FADD, FMUL). The method of the present invention adds the statements "x:=a+b" and "y:=a*b" to two different computation block nodes (cbn) because both are based on the same information "a" and "b". The "log2(x)" statement is appended to "x=a+b" because it uses the information "x". Since the information "y" is transferred, the information is available to both independent computation chains.

[0043] (ii) "Calculation matrix" and "Transfer matrix" As described above, the method of the present invention takes from such a flow graph of compute block nodes two technically defined matrices, referred to in this application as the “computation matrix” and the “transfer matrix,” both of which are numerical matrices. The “computation matrix” contains the instruction chain, and the “transfer matrix” contains the possible transfer properties (between other compute block nodes). Thus, the code extracted from the matrices always forms the pattern “computation->communication,” as will be described in more detail in the following sections. When the code is mapped to a single unit, the communication portion disappears, and the method of the present invention is reduced to an approach using “basic blocks,” which can also be processed by a state-of-the-art compiler. Referring to an example from Figure 7 of this form, we can see that unit 2 can compute the long-running instruction “log2(y)” and unit 1 processes the loop by incrementing a ("a=a+1") (see Figure 8). To see how this works, the matrix builder is shown in detail in the following section.

[0044] The term "matrix" is used to name the structure (m × n × p), and here,

number

[0045] The "numerical matrix" can be used as another well-formatted form to represent graph / tree-like structures, so it is also possible to work without the "numerical matrix" and perform all optimization / mapping in graph / tree form. Whether in mathematical or computational form, it represents the transfer dynamics of transfers and computations that occur in all binary-based electronic computing systems, represented using groups of instructions (referred to here as computation block nodes) and "transmit packages" as mentioned in Figure 23, for example. This is based on the grouping of instructions (e.g., any form of instruction / operation representing the form of an electronic circuit) within code (any form of code (high-level, assembly, etc.)) based on the rule of placing instructions that "read" information A in the same group (referred to here as computation block nodes) where instructions that "write" information A are located. This is significantly different from the grouping of instructions by well known basic blocks. When dependencies are not clear (as shown in Figure 21 for a graph element with two "read" nodes and one "write" node per instruction), a "transfer" is introduced between two compute block nodes (from the node holding the "write" instruction to the node holding the "read" instruction). In this form, the code can be represented in the form of compute block nodes connected by the necessary transfers. This information can be contained in a graph / tree, array, or any suitable structure. To execute these instructions on given hardware, a well-known method in state-of-the-art compilers can be used to optimize the chain of compute block nodes that group the instructions, and then, for each unit, it can be executed on the compute units involved (in this case, called transpiling), but it is not necessarily required.

[0046] (iii) How to return to the "matrix builder" and code After parsing the code and adding all instructions to compute block nodes (CBNs), each compute block node can be enumerated according to its position in the flow graph. This leads to a similar form of the control flow graph, given by the edges between CBNs and the connections of defined branch nodes. Using these positioning numbers, and using the unique position of the code in the flow, information about what to compute and what to transfer is placed into two matrices, the "computation matrix" and the "transfer matrix," where the "computation matrix" is for computation and the "transfer matrix" is for transfer. It is clear that metadata such as the size of the data required for each CBN and the size of transfers between CBNs can be easily derived.

[0047] Matrices represent a far more scalable form of access information than graphs and demonstrate the qualified nature of control flow graphs. They are not absolutely essential to this method, and this step can also be performed directly on graph / tree structures. However, the definition of block nodes also demonstrates the general nature of matrices in this invention: each row has an independent flow (dependency by transfer) of instructions (=computation) and necessary transfers (=communication) to other CBNs. It is guaranteed that a) no further information is needed to compute all instructions within a compute block node (which is similar to a basic block, but with a completely different scope of independence), b) the information used is not changed anywhere else during the same compute step in the entire code, and c) information unaffected by the computation during this time step can be transferred. This fact means that each cell in the compute matrix has all instructions that can be computed simultaneously and independently of all instructions in other cells in the same column. In the transfer matrix within each cell, the transfers (corresponding cells in the compute matrix) required at the beginning and end of each compute step are known. Retrieving code to run on different units results in expressions of the form "communication -> compute -> communication -> compute". Each row represents a chain of compute and communication properties that form a series of computes linked together by communication with other rows = chains of computes. The information necessary to communicate with other rows = chains is in the transfer matrix. Each row in the compute matrix (and the same combination in the transfer matrix) can also be combined with any other row in the matrix (computing all instructions in both combined cells and making the necessary transfers for both cells based on the transfer matrix) to create a new combination of compute <-> transfer behavior for a given code. In this step, computes are added together and transfers on the same unit are (by combination) eliminated. This later leads to the fact that a simple form of optimization, as well as the fact that the optimization / mapping step reliably results in executable code, since iterative solutions or similar methods are not required.Debugging parallel code is extremely complex, so this is another example of parallelized code that is a well-known technical problem (see, for example, A. Danner et al., "ParaVis: A Library for Visualizing and Debugging Parallel Applications").

[0048] Each row of the computation matrix represents a chain of instructions for a single unit, as defined herein. A unit depends on the level of implementation (e.g., bare assembly, thread, process, compute node, etc.). Naturally, empty blocks (empty cells in the computation matrix) or unused communication entries (empty cells or transfers on the same unit in the transfer matrix) disappear, and the start and end communication links also disappear along with them, as seen in Figure 10. This results in cases where there are no transfers when the code is executed on a single unit, and all transfers disappear by obtaining optimized code for a given unit through variable reallocation / renaming or the application of well-known optimization methods in state-of-the-art compilers.

[0049] Depending on the method of communication, it is guaranteed that information used in instructions is not transferred simultaneously within the computation block node, and that the same is true for other CBNs with the same number, so a non-blocking or blocking mechanism can be used. Depending on the level, the computation and communication parts can be implemented, and as a result, this method can be used as a compiler or transpiler. When converted back to code in the form of "computation -> communication", the language most suitable for the application (e.g., C, C) can be used. ++ The use of Python becomes easier, and this depends on the target infrastructure, such as the use of IPC (InterProcess Communication) methods (e.g., queues / pipes, shared memory, MPI (Message Passing Interface)), libraries (e.g., eventlibs, multiprocessinglibs) and available state-of-the-art compilers.

[0050] (iv) "Optimization" The general and clearly defined properties of the matrix provide a unique base for a wide range of possibilities for mapping / optimizing code to given hardware or evaluating the optimal hardware configuration for a given code (see, for example, variations E1-E5 of different embodiments in Figure 106). This structure, as a result, guarantees executable code. Each hardware infrastructure has its own performance properties, and combined with the available software layers, modern ICT (Information and Communications Technology) infrastructure is extremely complex. The method of the present invention makes it possible to optimize code for hardware or to provide ideal hardware. Most obviously, it involves constructing different combinations of rows from the compute and transfer matrices, so that the same combinations are constructed in both matrices. Each combination (e.g., a combination of row 1 and row 2 in the compute and transfer matrices) is then a new version of the parallel / concurrent code for a given input code, and its properties on the target infrastructure (see Figure 11 for a simple example) can be evaluated.

[0051] Different combinations of rows in a matrix (for example, combining row 1 and row 2 or row 2 and row 5 in the computation matrix and transfer matrix) yield different combinations of computation-to-communication ratios. Each of these combinations can then be examined, containing other known metadata about the given hardware / software infrastructure. For example, a data type called datanode() can be used to evaluate hardware properties such as cache length, available memory, or other properties of the target platform. This form of searching for the optimal computation-to-communication ratio for a given code and hardware does not require iterative solutions or similar approaches to find a solution in the optimization step, and does not result in solutions with race conditions, deadlocks, etc., although deadlocks may be detected, thus always yielding executable concurrent code.

[0052] Instruction grouping is based on the inherent physical constraint that transfers are typically orders of magnitude larger than computing at the same "location," and this method generates a form of optimal solution space for the most divisible form of the code, resulting in a search space for a clear and unique method to find the optimal map for given hardware, or ideal hardware for given code. This makes this method very general and solves the technical problem of automatically adapting given code to a target platform. When this method is used as a transpiler, a state-of-the-art compiler can be used to optimize the code for the target hardware / unit.

[0053] Other methods do not utilize the inherent time properties and dependencies given by the code, nor do they generate a unique solution space of this form for optimization in the form of a method definition of computational block nodes (by grouping them without changing the information), which in many ways directly solves the technical problem. The examples in the detailed explanation illustrate this in more detail.

[0054] (v) The "computation block node" according to the present invention and the "basic block or slice" of the prior art Computation block nodes are not the same as basic blocks or slices. They have different scopes. They do not follow the definition of basic blocks, for example, by connecting independent program parts based on their jumps / branching. Instruction chains within a computation block node have fundamental data dependencies, meaning that the information used in these chains is not simultaneously modified or transported anywhere else in the given code / program step.

[0055] Therefore, the time or location of instructions within a program is made dependent within the compute block node. A compute block node consists of a chain of instructions based on the same information, defined as any form of bit pattern (e.g., data variables, pointer addresses, etc.). The correlation of both physical and physical time is achieved within the compute block node by introducing transfers / communications that are coupled with instructions, as well as the information being used by time steps within the code. This method arranges the compute blocks so that for every point in time, it is determined which information can be transferred where and which information can be computed in parallel. This gives a different perspective, in particular, on optimization techniques. There is a wide range of technical problems that can be solved by this change in perspective. A compute block node links the location of information (bit patterns) within the compute framework to the time when this information is used within the program. This is supported by the fundamental physical principles of computation in classical infrastructure. The following example with nested loops and arrays demonstrates this effect well. Branches in loop definitions can be translated into reading and writing data points according to arrays when distributed across parallel compute block nodes.

[0056] The method of the present invention divides code into computational segments and determines where the resulting information must be transported. Thus, by defining computational block nodes, the method generates a matrix system where instructions based on the same information are grouped together, and constrained that, at any given point in time, the same information is not needed anywhere else in the infrastructure. Grouped instructions cannot be further divided because any form of transport would be longer than the computation of this given chain at the computational block node, thus preventing faster computation for a particular group of instructions. As shown, the general properties of computational and transport matrices allow for the optimization of the divided code to be the most concurrently executable solution possible for given hardware. The ratio of computation to transport depends on the target hardware, and the method provides different solutions for dividing a given code into different ratios. By converting dependency graphs into matrices, these can be used in a more effective way to map / optimize the divided code to a target platform that includes specific properties of this infrastructure (e.g., a GPU requires different transport / computational processing than a CPU). However, using matrices is not mandatory, and optimization / mapping can be performed directly on graph / tree structures.

[0057] (vi) "Idle time" - "Waiting time" The latency as defined herein is given by the idle time of the processing unit 21 from the time it processes a particular block of instructions in processing code 32 for data and sends the data back to the parallel processing system 2 until it receives the data necessary to execute a succession of instructions in processing code 32 by the same processing unit 21 (i.e., after retrieving and / or fetching the data). In contrast, idle time of a processing unit can be defined herein as the amount of time during which the processing unit is not busy between two compute block nodes, or the amount of time during which the processing unit performs idle processes of the system. Thus, idle time makes it possible to measure the unused capacity of the processing units in a parallel processing system. Maximum speedup, efficiency, and throughput are in the ideal case of parallel processing, but these are not achieved in practice because the speedup is limited by various factors that contribute to the idle time of the processing units. The idle time of a processing unit as used herein can be found in various causes, including, among others: (A) data dependencies between succession of compute block nodes (i.e., tasks that cannot be further divided, framed by read / write operations): dependencies may exist between instructions in two compute block nodes. For example, one instruction cannot start until the previous instruction returns a result, because they are interdependent. Another example of data dependency is when both instructions attempt to modify the same data object, which is also called a data hazard. (B) Resource constraints: If resources are not available at runtime, delays occur in pipelined execution. For example, if one shared memory is used for both data and instructions, and instructions need to be read / written and retrieved simultaneously, only one can execute and the other must wait. Another example is a limited resource such as an execution unit that may be busy at the requested time. (C) Branch instructions and interrupts in a program: A program is not a linear flow of sequential instructions. There may be branch instructions that change the normal flow of the program, which can delay execution and affect performance.Similarly, there may be interrupts that postpone the execution of the next instruction until the interrupt is served. Branches and interrupts can negatively impact the minimization of idle time.

[0058] Tasks that minimize idle time are also referred to as "load balancing," and it should be noted that this means distributing work among processing units so that all processing units remain busy at all times under ideal conditions.

[0059] (vii) “Basic Command” As used herein, the terms “basic operation” or “basic instruction” refer to machine operations that do not include simpler operations. These are at the machine language level. However, in variations of certain embodiments, they may include at least microcode instructions, or consist entirely of microcode instructions. Microcode is the result of interpreting low-level machine language, and microcode instructions directly manage hardware resources at the register or circuit level. Machine language interprets machine instructions and sends them to the lowest hardware layer level, where they are translated into small microprograms called microcode. Thus, microcode is low-level code that defines how a microprocessor should function when executing machine language instructions. Typically, one machine language instruction is translated into several microcode instructions.

[0060] As described above, the execution of a basic instruction typically consists of a sequence of operations, including, as defined above, register resets, memory storage resets, one-digit left or right shifts of characters in registers, data transfers between registers, data item comparisons, logical additions, and logical multiplications. A set of basic operations can provide a structure for executing a particular instruction. Basic operations include the basic logic functions of logic gates, including AND, OR, XOR, NOT, NAND, NOR, and XNOR. Such basic operations can be assumed to take a fixed amount of time on a given processing unit, which may vary by a fixed coefficient when executed on different processing units 21 or parallel processing systems 2.

[0061] Based on the concept of microcode instructions, the design of integrated circuits such as field-programmable gate arrays (FPGAs) and application-specific integrated circuits (ASICs) involves several levels of abstraction, from high-level algorithmic description to low-level hardware description. These descriptions are written in hardware description languages ​​(HDLs), which allow designers to define the function and behavior of those circuits at a very low level, or, increasingly, the high-level synthesis (HLS) process is applied to describe the behavior of digital systems using high-level languages ​​such as C or C++. Logic synthesis tools are similar to compilers for hardware, mapping HDL code to a library of gates called standard cells to minimize area while satisfying several timing constraints. This generates a register transfer-level (RTL) description of the system, which defines how data flows between registers and how calculations are performed using arithmetic logic units (ALUs) or simple logic gates that implement Boolean functions or arithmetic. The RTL description is then synthesized into gates and flip-flops to generate a gate-level synthesis (GLS) netlist. The netlist is the lowest level of abstraction and represents the actual hardware implementation of the digital system.

[0062] Since computation block nodes group these essential logical operations, logic gate layouts can be derived from computation block nodes so that each consists of basic gates such as NOT, AND, OR, XOR, NAND, NOR, and XNOR, or more complex gates such as multiplexers, decoders, adders, subtractors, shifters, multipliers, and dividers. Given that computation block nodes are already a set of basic operations, they can also be viewed as a sequence of Boolean functions and / or arithmetic.

[0063] In the first step, which will be described in more detail below, the system of the present invention converts the source code into a sequence of basic operations 321, ..., 325 or code 32 structured with loops, branches, and sequences. This is independent of platform and compiler optimization levels and therefore the same conversion can be used to optimize execution time on any platform.

[0064] This approach is based on decomposing a single source code 31 written in a programming language into basic operations 32 / 321, ..., 325, i.e., separate transformed parts of source code 31. The set of basic operations is finite for each processing unit, having several subsets of integer, floating-point, logical, and memory operations. These sets are interrelated to parts of the processor architecture and memory data paths. The basic operations used herein can be classified into various levels, for example: the top level includes four operation classes: INTEGER, FLOATING POINT, LOGIC, and MEMORY. The second level of classification can be based on the origin of the operands (i.e., their location in memory space), i.e., local, global, or procedural parameters. Each group can exhibit different timing behaviors, with frequently used local variables almost always being in the cache, while global and parameter operands must be loaded from arbitrary addresses and can cause cache misses. The third level of classification is by operand type, i.e., (1) scalar variables and (2) arrays of one or more dimensions. A pointer is treated as a scalar variable if its value is given using a single variable, and as an array if its value is given using multiple variables. The operations belonging to the INTEGER and FLOATING POINT classes are addition (ADD), multiplication (MUL), and division (DIV). The LOGIC class includes logical operations (LOG): (i.e., AND, OR, XOR, and NOT) and shift operations (SHIFT): operations that perform bitwise movements (e.g., rotation, shift, etc.). The operations of the MEMORY class are as follows: single memory allocation (ASSIGN), block transaction (BLOCK), and procedure call (PROC). MEMORY BLOCK represents a transaction of a block of size 1000 and can only have array operands. MEMORY PROC represents a function call with one argument and a return value.Arguments can be variables and arrays that are declared locally or provided as parameters to the calling function, but are not global.

[0065] (viii) "Processor" - "Core" To define the term “core” as used herein, for example, “multicore processor,” a definition of the term “processor” (or “microprocessor”) must also be given. In computing terminology, a processor is a component that reads and executes program instructions. A processor core is a processor, or individual processing unit, within the central processing unit (CPU) of a computer. Instructions for a processor are technical signals to the processor / core 2102 / 2103 that tell it what to do, such as reading data from memory or sending data to an output bus. The most common type of processor is the central processing unit (CPU). A multicore processor is generally defined as an integrated circuit with two or more independent processors (called cores) mounted on it. This term refers to having multiple CPUs that are not mounted on the same integrated circuit. It should be noted that this is related to, though not the same as, the term "multi-CPU". In conventional technology, the term uniprocessor generally referred to having one processor per system [uniprocessor], and that the processor had one core. This term is used in contrast to multi-processing architectures, i.e., multi-core, multi-CPU, or both. Multi-core processors emerged in the computing industry from uniprocessor technology as a way to achieve higher performance through parallelism rather than raw clock speed. Over the years, the computer industry has developed increasingly faster uniprocessors, but this pursuit is nearing its end due to the limits of transistor scaling, power requirements, and heat dissipation. As single-threaded cores have reached a plateau in clock frequency, chip manufacturers are turning to multi-core processors to improve performance using parallelism.

[0066] (ix) Types and performance of parallelization in multicore CPUs Since multicore CPUs fundamentally rely on parallelism to improve performance, understanding the main types of parallelism is crucial for analyzing performance and comprehending the technical issues associated with automated parallelization systems. A modern multicore processor without code parallelism is meaningless. However, while parallelism is a technically extremely difficult and complex subject, in the context of this invention, it is sufficient to understand three basic types of parallelism: instruction-level parallelism, thread-level parallelism, and data-level parallelism. These are all employed by various multicore CPU architectures and have different impacts on performance, which must be understood in order to conduct a thorough performance analysis.

[0067] Instruction-level parallelism (or ILP) is a first type of parallelism that involves executing certain instructions of a program simultaneously that would otherwise be executed sequentially, and which can have a positive impact on performance depending on the instruction mix of the application. Conventional techniques, many CPUs employ instruction-level parallelization techniques such as pipelining, superscalar execution, prediction, out-of-order execution, dynamic branch prediction, or address speculation. However, only certain parts of a given program's instruction set may be suitable for instruction-level parallelization, as shown in the example in Table 2 below. [Table 1]

[0068] Since steps 1 and 2 of sequential execution are independent of each other, a processor using instruction-level parallelism can execute instructions 1.A and 1.B simultaneously, thereby reducing the number of operation cycles required to complete the operation by 33%. However, the final step depends on the two preceding steps and must therefore be executed sequentially in all cases. It is clear that this example is an oversimplification. Nevertheless, in automated parallelization systems, it is important to identify which parts of an application have instructions that can be executed in parallel.

[0069] Thread-level (or task-level) parallelism (TLP) is a second type of parallelism that involves executing individual task threads delegated to the CPU concurrently. Thread-level parallelism can substantially impact the performance of multithreaded applications through a variety of factors ranging from hardware-specific and thread implementation-specific to application-specific, and therefore a fundamental understanding of this type of parallelism is crucial. Each thread maintains its own memory stack and instructions, and as a result, can be considered an independent task, even if the threads may not actually be truly independent within the program or operating system. Thread-level parallelism is used by programs and operating systems with multithreaded designs. Conceptually, it is easy to understand why thread-level parallelism can improve performance. If the threads are truly independent, distributing a set of threads across the available cores on the processor will reduce the elapsed execution time to the maximum execution time of any one of the threads compared to a single-threaded version that requires the additional execution time of all threads. Ideally, the work is also evenly divided among the threads, minimizing the overhead of thread allocation and scheduling. In the real world, this simple ideal model of thread-level parallelism performance is complicated by several technical factors, and as a result, the ideal scenario is rarely observed in actual applications. Factors affecting performance include load balancing, the level of execution independence, thread locking mechanisms, scheduling methods, and required thread memory. Furthermore, data-level parallelism between distributed threads can also affect performance. Thread implementation libraries in both the operating system and specific applications also impact performance.

[0070] Data-level parallelism (DLP) is a third type of parallelism that involves sharing common data between executing processes via memory coherence, improving performance by reducing the time required to load and access memory. Identifying application areas that typically utilize data-level parallelism helps in understanding performance characteristics on multi-core processors.

[0071] Loop-level parallelism (LLP) is a fourth type of parallelism in which loop iterations are executed in parallel if they have no dependencies on each other. If all loop iterations require the same execution time, the distribution can be done by static distribution with a fixed number of iterations to each computation unit.

[0072] In the context of multi-core CPUs, data-level parallelism in cache memory shared by cores can have a substantial impact on performance. Here, execution processes running on multiple cores are called threads. Performance improvements can be expected when threads read from the same data in shared memory. This scenario allows multiple threads to use a single copy of the data, reducing the number of replication operations and therefore the execution time. If threads do not share common data, each thread must maintain a copy of that data, yielding no benefit. However, if multiple requests to this memory exceed its bandwidth, an increase in threads can negatively impact performance. Furthermore, performance impacts can also occur during write operations. Multiple threads attempting to write to the same memory location simultaneously must wait to resolve the contention. To address this problem, mechanisms such as spinlocks are needed to handle such situations. The performance impact depends on the penalties associated with the mechanism used and how frequently such contentions occur. Generally speaking, having threads write to different regions of shared memory is preferable to reduce the likelihood of incurring these penalties. NUMA (Non-Uniform Memory Architecture) can be beneficial because it places data used by a particular core more physically close to that core in memory. Furthermore, bandwidth becomes a crucial factor here as the number of threads increases on multi-core processors. Limited cache size (cache misses), limited bandwidth, off-cache latency, and other aspects affect performance, but data-level parallelism can improve performance in some situations. Moreover, the interaction between instruction-level parallelism and data-level parallelism affects performance. Flynn's classification provides a technical framework for analyzing these interactions. In summary, observations about data-level parallelism in a particular application can be important for analyzing its performance on a multi-core CPU, as memory is often a limiting factor.

[0073] (x)P and NP fully automatic parallelization measures In the fields of computer technology, code parallelism, and processor architecture, numerous systems and methods address the technical problem of improving the speed and memory space required to compute code and algorithms. Faster algorithms provide extra time for more computation, and less space required further enhances computation, especially parallel computing. As mentioned, the time it takes for a computer to compute a problem is called "time complexity," and the space taken up is called its "spatial complexity." The time and space required to execute these algorithms are typically measured by the size of the input and the number of elements the algorithm must operate on. There is another measure related to the two mentioned above. So-called "computational complexity" is a measure for classifying computational problems according to their resource usage and relating these classes to one another. A computational problem is a task that is solved by a computer and its processor. A computational problem is a technical problem that can be solved by the mechanical application of processing steps by a processor and data processing means as a data repository.

[0074] A computational problem is considered inherently difficult if its solution, whatever processing steps or algorithms are used, requires significant resources. To provide a measure, computational models are used, among other things, to quantify the complexity of a computation, i.e., the amount of resources required to solve a particular problem, such as time and storage. Other measures of complexity include, for example, the amount of communication (used in "communication complexity"), the number of gates in a circuit (used in "circuit complexity"), and the number of processors (used in parallel computing).

[0075] One role of computational complexity is to provide a measure of the practical limits of computers or parallelization. On the other hand, if a computational problem is considered easily solvable, it means that the problem (in this case, automated parallelization) can be solved quickly using computer means. The term "quickly" as used above means that the processing code or algorithm that solves the task runs in polynomial time, and the time to complete the task changes as a polynomial function of the size of the input to the algorithm (as opposed to exponential time). A general class of questions for which several algorithms can provide a solution in polynomial time is called "P," meaning polynomial. Thus, the time and space to find the solution (i.e., the parallelized code) for an input n is, for example, n 1 , n 2 , n 99 Parallelization problems that increase in polynomial time as n is raised to a power, like this, belong to the "P" class. On the other hand, the class of parallelization problems where the time to provide a solution increases exponentially, that is, not in polynomial time, is called "NP" (Nondeterministic Polynomial time). Unlike parallelization problems in P, NP parallelization problems require a very long time and space for a computer to solve, and this time increases exponentially as the number of elements in the input increases. This exponential time is, for example, 2 n It is described as any number being raised to the power of n.

[0076] In this regard, it should be noted that for some problems, there is no known method for quickly finding a solution, but if information is provided indicating what the answer is, it is possible to quickly verify the answer. In terms of a measure of computational complexity, such technical problems are called NP-complete ("non-deterministic polynomial-time complete"), where "non-deterministic" refers to a non-deterministic Turing machine, "complete" refers to the property that all of the same complexity class can be simulated, and "polynomial-time" refers to the amount of time that a deterministic method is considered "quick" for checking a single solution, or for a non-deterministic Turing machine to perform the entire search. That is, a computational problem is NP-complete if (i) the correctness of each solution can be quickly (i.e., in polynomial time) and the solution can be found by using a brute-force search by trying all possible solutions, and (ii) the problem can be used to simulate all other problems for which it is possible to quickly verify that the solution is correct. In this sense, NP-complete problems are the most difficult problems for which the solution can be quickly verified. If a system or algorithm can quickly find the solution to a given NP-complete problem, then this system or algorithm can quickly find the solutions to all other problems for which a given solution can be easily verified. In computational techniques, this problem is called the "P vs. NP problem," which is whether a problem that can be verified in polynomial time can also be solved in polynomial time. This problem has great technical implications, among other things, for the parallelization of code and the power of the systems or methods used for parallelization. In particular, if a parallelization system and / or method can provide parallelization for a particular code or code structure, and this code or code structure is an NP-complete problem, then all other similar NP-complete codes and code structures can be parallelized to the same extent by this parallelization system or method, except for the polynomial reduction time.For code parallelization, it is obvious that, in principle, brute force can always be used to search for the best-optimized parallelism by generating in parallel all possible basic blocks or compute block nodes or all possible permutations of tasks or threads, including all possible permutations of instructions, and then testing them. However, using brute force often leads to an exponential increase in the complexity of code parallelization, resulting in the computational power of the computer being applied no longer scaling. Some conventional solutions attempt to perform branch and bound methods on different tasks or threads by taking different choices or assumptions. However, tuning tasks / threads becomes more difficult, and deriving and / or verifying the best-optimized parallel code becomes a technically challenging task.

[0077] [Detailed description of the embodiment] Figures 12 and 13 schematically illustrate architectures for possible implementations of an embodiment of a compiler system 1 for optimized compilation of program code 3 for execution by a parallel processing system 2 having multiple processing units 21. Note that in this specification, when an element is referred to as “connected” or “bonded” to another element, it may be directly connected or bonded to that other element, or there may be an intervening element. On the other hand, when a component is referred to as “directly connected” or “directly linked” to another component, there is no intervening element. Furthermore, some parts of the following detailed description are presented with respect to procedures, logical blocks, processes, and other symbolic representations of operations on data bits in computer memory. These descriptions and representations are means used by those skilled in the art to most effectively communicate the content of their work to others skilled in the art. In this application, procedures, methods, logical blocks, processes, etc., are considered to be a consistent sequence of steps or instructions leading to a desired result. Modifications of the embodiments described herein may be described in the general concept of processor-executable instructions residing on some form of non-temporary processor-readable medium, such as program code or code blocks, which are executed by one or more processors or other devices. Generally, program code includes routines, programs, objects, components, data structures, etc., that perform a particular task or implement a particular abstract data type. The functionality of the program code may be combined or distributed as desired in various embodiments. Techniques described herein may be implemented in hardware, software, firmware, or any combination thereof, unless specifically described as being implemented in a particular way. Any feature described as a module or component may also be implemented together in an integrated logic device, or separately as individual but interoperable logic devices.When implemented in software, the technique can be at least partially realized by a non-temporary processor-readable storage medium containing instructions that, when executed, perform one or more of the methods described above. The non-temporary processor-readable data storage medium may form part of a computer program product. In the case of firmware or software implementations, the methodology can be implemented using modules (e.g., procedures, functions, etc.) having instructions that perform the functions described herein. Any machine-readable medium that tangibly embodies the instructions may be used in implementing the methods described herein. For example, software code may be stored in memory and executed by one or more processors. Memory may be implemented, for example, as registers within or outside the processor.

[0078] Various exemplary logic blocks, modules, circuits, and instructions described in relation to embodiments disclosed herein include, for example, a processor 2102 with a control unit 2101, registers 21021 and combinational logic 21022, and / or a graphics processing unit (GPU) 211, and / or a sound chip 212, and / or a vision processing unit (VPU) 213, and / or a tensor processing unit (TPU) 214, and / or a neural processing unit (NPU) 215, and / or a physical processing unit (PPU) 216, and / or a digital signal processor (DSP). The functions described herein may be performed by one or more processors or processor units 21, such as one or more central processing units (CPUs) 210, including 217 and / or synergistic processing units (SPUs) 218 ​​and / or field-programmable gate arrays (FPGAs) 219, or any other processor unit 21 known in the art as, for example, a motion processing unit (MPU) and / or a general-purpose microprocessor and / or an application-specific integrated circuit (ASIC) and / or an application-specific instruction set processor (ASIP), or any other equivalent integrated or discrete logic circuit. The terms “processor” or “processor unit” 21 used herein may refer to any of the above-described structures or any other structure suitable for implementing the techniques described herein. In addition, in some embodiments, the functions described herein may be provided within a dedicated software module or hardware module configured as described herein. Furthermore, the techniques may be fully implemented in one or more circuits or logic elements. The general-purpose processor 21 may be a microprocessor, but alternatively, the processor may be any conventional processor, controller, microcontroller, or state machine. In the embodiments described, the processing elements refer to a plurality of processors 21 and related resources such as memory or memory units 22.Some exemplary methods and apparatus disclosed herein may be implemented, in whole or in part, to facilitate or support one or more operations or techniques for processing code in multiple processors. A multiprocessing system 2 may also include a processor array comprising multiple processors 21. Each processor 21 in the processor array may be implemented in hardware or a combination of hardware and software. The processor array may represent one or more circuits capable of performing at least a portion of an information computing technique or process. As an example, but not an limitation, each processor in the processing array may include one or more processors, controllers, microprocessors, microcontrollers, application-specific integrated circuits, digital signal processors, programmable logic devices, field-programmable gate arrays, or any combination thereof. As stated above, the processor 21 may be a general-purpose central processing unit (CPU), or a dedicated processor such as a graphics processing unit (GPU), a digital signal processor (DSP), a video processor, or any other dedicated processor.

[0079] The present invention includes a compiler system 1 having subsystems 11, ..., 16. In a non-limiting embodiment, the subsystems include at least a lexer / parser 11 and / or analyzer 12 and / or scheduler 13 and / or matrix module 14 and / or optimizer module and / or code generator 16. They may also include a processor array and / or memory. The compiler 1 segments the code into code blocks. In the embodiments described, a block or code block refers to a section or portion of code that is grouped together. Grouping allows a group of statements / instructions to be treated as a single statement and allows the scope of variables, procedures, and functions declared within a block to be limited so as not to conflict with variables that have the same name used elsewhere in the program for different purposes.

[0080] The memory or memory unit 22 of the parallel processing system 2 described above may include any memory for storing code blocks and data. Memory 22 may represent any suitable or desired information storage medium. Memory may be coupled with the processor unit 21 and / or processing array. As used herein, the term “memory” 2 refers to any type of long-term memory, short-term memory, volatile memory, non-volatile memory, or other memory, and is not limited to a specific type of memory or the number of memories or the type of medium in which the memory is stored. Memory 2 may include, for example, a primary storage unit 211 as a processor register 2111, and / or a processor cache 2112 including a multilevel cache such as an L1 cache 21221, an L2 cache 21222, and / or a random access memory (RAM) unit 2113. In this application, it should be noted that the problem with multilevel caches is a trade-off between cache latency and hit rate. A larger cache has a better hit rate but has longer latency. To address this trade-off, multiple levels of cache can be used, with a smaller, faster cache backed up by a larger, slower cache. Multilevel caches generally operate by first checking the fastest, Level 1 (L1) cache. If it hits, the processor can proceed faster. If that smaller cache misses, the next fastest cache (Level 2, L2) is checked before accessing external memory, and so on. Cache access is not directly controlled by the programmer; it can be influenced by data locality and / or compiler hints. As the latency difference between main memory and the fastest cache (see Figure 1) increases, some processors are beginning to utilize as many as three levels of on-chip cache.Memory 2 may further include, for example, a secondary storage unit 212 and / or a third storage unit 213 (e.g., tape backup), and the secondary storage unit 212 may include, for example, a hard disk drive (HDD) 2121 and / or a solid-state drive (SSD) 2122 and / or a universal serial bus (USB) memory 2123 and / or a flash drive 2124 and / or an optical storage device (CD or DVD drive) 2125 and / or a floppy disk drive (FDD) 2126 and / or a RAM disk 2127 and / or a magnetic tape 2128. In at least some implementations, one or more portions of the storage medium described herein may store signals representing information represented by a particular state of the storage medium. For example, an electronic signal representing information may be “stored” in a portion of the storage medium (e.g., memory, register, flip-flop, etc.) by influencing or changing the state of such portion of the storage medium to represent the information. Therefore, in certain implementations, such a change in the state of a portion of the storage medium for storing signals representing information constitutes a conversion of the storage medium to a different state or object. As stated, memory 2 can include, for example, random access memory (RAM), first-in, first-out (FIFO) memory, such as synchronous dynamic random access memory (SDRAM), or other known storage media. A (micro)processor is based on an integrated circuit that enables arithmetic and logical operations based on (two) binary values ​​(most simply 1 / 0). For this purpose, the binary values ​​must be available to the processor's compute unit. The processor unit needs to obtain two binary values ​​in order to compute the result of the expression a=b operand c. The time it takes to retrieve the data for these operations is known as latency. These latency from registers, L1 cache, memory access, I / O operations, or network transfers, as well as from processor configurations (e.g., CPU vs. GPU), has a wide hierarchical range.Since every single component has latency, the overall latency for a computation is primarily the combination of hardware components required to retrieve data from one location to another in modern computing infrastructure. The difference between the fastest and slowest locations for a CPU (or GPU) to retrieve data can be very large (10). 9 (A range exceeding double).

[0081] From a general perspective, latency is the time delay between the cause and effect of some physical change in a system being observed or measured. As used herein, latency is directly related to the physical structure of the multiprocessing system 2. The multiprocessing system 2 includes a processor unit 21 based on an integrated circuit that enables arithmetic and logical operations based on (two) binary values ​​(most simply 1 / 0). These binary values ​​must be available to the processor's compute unit. The processor unit needs to obtain the two binary values ​​to compute the result of the equation a=b operand c. The time it takes to retrieve the data for these operations is known as latency. These latency from registers, L1 cache, memory access, I / O operations, or network transfers, as well as processor configurations (e.g., CPU vs. GPU), have a wide hierarchical range. Since every single component has latency, the overall latency for compute is primarily the combination of hardware components required to retrieve data from one place to another within the multiprocessing system's infrastructure. It should be noted that while microprocessor speeds have increased more than tenfold every decade, general-purpose memory (DRAM) speeds have only doubled, meaning access times have only been halved. Therefore, memory access latency relative to processor clock cycles increases sixfold every decade. Multiprocessor systems exacerbate this problem. In bus-based systems, establishing a high-bandwidth bus between the processor and memory tends to increase latency to retrieve data from memory. If memory is physically distributed, network and network interface latency is added to the latency to access local memory on the node. Latency typically increases with the size of the multiprocessor machine, as more nodes mean more communication relative to computation, more jumps in the network for general communication, and possibly more contention.The primary goal of parallel computing hardware design is to reduce overall latency used for data access by maintaining high scalable bandwidth, while the primary goal of parallel processing coding design is to reduce overall idle time of the processor unit 21. Generally, idle time of the processor unit 21 can have several causes, such as memory access latency, deadlocks, or race conditions, if the sequence or timing of code blocks or threads processed by the processor unit 21 are interdependent, i.e., dependent on the relative timing between interfering threads. As used herein, a deadlock is a state in which a member of the processor unit 21 is waiting for the output of another member, e.g., the output of an instruction block processed by another processor unit 21, to take action. Deadlocks are a common problem in multi-processing systems, parallel computing, and distributed systems, where software and hardware locks are used to arbitrate shared resources and implement process synchronization. Therefore, as used herein, a deadlock occurs when a process or thread enters a waiting state because the requested system or data resource is being held by another waiting process, or has not yet been achieved by that process, and that process may be waiting for another resource or data being held by another waiting process. If a processor unit 21 is unable to process a resource requested by it because it is being used by another waiting process (data access or output by another processor unit 21 that has not yet terminated), this is referred to herein as a deadlock that leads to idle time for each processor unit 21.

[0082] The compiler system 1 includes means for converting the source programming language 31 of a computer program 3 into machine code 32 as a target programming language that generates processing code 3.1, ..., 3.n containing several instructions executable by multiple processing units 21 of the parallel processing system 2, or controls the operation of the multiple processing units 21. The source programming language can be, for example, a high-level programming language 31. The high-level programming language 31 can include, for example, C and / or C++ 311 and / or Python 312 and / or Java® 313, Fortran 314, OpenCL (Open Computing Language) 315, or any other high-level programming language 31. It is important to note that the automated parallelization compiler system 1 can also be applied to machine code 31 or assembler code 31 as source code in order to achieve parallelization of the code. In this case, the conversion from high-level language to machine code instructions does not need to be performed by the compiler system 10.

[0083] The parallel processing system 2 includes a memory unit 22 that includes at least a main execution memory unit 221 / 2212 having multiple memory banks for holding at least some of the data of the processing code 32, and a transition buffer unit 221 / 2211 having high-speed memory for storing the starting position of the processing code 32 and a data segment having at least a branch or jump instruction and / or a memory reference and data value, wherein the main execution memory unit 2212 provides a slower access time than the transition buffer unit 2211. The transition buffer unit 2211 may include, for example, a cache memory module 2211 and / or an L1 cache 22121.

[0084] The execution of processing code 32 by the parallel processing system 2 includes the occurrence of a delay 26, which is given by the idle time of the processing unit 21 for retrieving and / or storing the data necessary for the execution of a particular block of instructions in processing code 32 by the processing unit 21. The delay may include, for example, the access time of register 2211 and / or the access time of L1 cache 22121 and / or the access time of memory 2213 and / or the I / O operation time and / or the data network transfer time and / or the processor configuration time.

[0085] The compiler system 1 includes a parser module 11 for translating a source programming language 31 into code 32 of basic instructions that can be directly executed by several processing units 21, the basic instructions being selectable from a set of processing unit-specific basic instructions including arithmetic operations 321 and / or logical operations 322 and / or control operations and / or I / O operations for several processing units 21, in particular variable and array declaration instructions 323, comparison operation instructions 324, and code flow instructions 325. Arithmetic operations 321 can include operations such as addition, subtraction, multiplication, and division. Logical operations 322 can include several logical expressions such as equal, not equal, greater than, less than, greater than or equal to, and so on. Control operations can include, for example, "branch expressions" and / or "loop expressions".

[0086] As a variation of the embodiment, at least two of the processing units may have, for example, different sets of basic instructions. Different processing units having different sets of basic instructions may include, for example, a central processing unit (CPU) 210, a graphics processing unit (GPU) 211, a sound chip 212, a vision processing unit (VPU) 213, a tensor processing unit (TPU) 214, a neural processing unit (NPU) 215, a physical processing unit (PPU) 216, a digital signal processor (DSP) 217, a synergistic processing unit (SPU) 218, a field-programmable gate array (FPGA) 219, and the like.

[0087] The parser module 11 includes means for partitioning the code of basic instructions into compute block nodes 333, each compute block node consisting of the smallest possible segmentation of a unit that cannot be further broken down, each containing a sequence of basic instructions that requires the same input data. Two or more compute block nodes 333, each having a chain of basic instructions, form a compute chain 34 that creates an ordered flow of operations / instructions for the input data. The chains (sequences of basic instructions) in the compute block nodes 333 are constructed by fixed rules: instructions are placed in a position in the chain 34 where a new basic instruction reads after a basic instruction that writes a data point. This automatically forms the chain 34, which is data-centric and maps the necessary physically restricted READ and WRITE operations in the CPU 21's compute registers 2211, L1 cache 2212, network I / O, etc.

[0088] Compiler system 1 includes a matrix builder 15 for generating several numerical matrices 151, ..., 15i from computation chain 34 according to latency 26. While the system dependencies can be evaluated in the graph from computation chain 34, they cannot be simply broken down into individual independent chains. Chain 34 contains fusion and division situations of computation block 333 chains arising from data dependencies and / or code branches. Latency for information delivery in the hardware system is introduced as physical time. By assigning at least this time interval length to each computation block node 333, each computation block node 333 in the graph or tree structure is numbered according to its position in the graph and given a block number, and thus computation block nodes 333 having the same "time position" in the graph can be given the same number. A set of matrices 151, ..., 15i can be constructed if the computation block node 333 must have at least the time length required to deliver information within the system, compute as many instructions as possible during this time, and each computation block node 333 has a number based on its position in the graph according to the program flow.

[0089] Matrices 151, ..., 15i also demonstrate that they can be mathematically captured (graph models based on CB, CC, etc., are not simply captured as tables / matrices). Thus, given data behavior and communication, numerical matrices can be constructed, which can be optimized (modified) by using, for example, ML or AI, depending on the target platform and / or hardware setup.

[0090] The compiler system includes a numerical matrix optimization module 16 that uses a numerical matrix optimization technique to minimize the total latency that occurs as a total latency 26 by providing an optimized structure for computation chains 34 processed by multiple processing units 21, and a code generator 17 generates optimized machine code for multiple processing units of a parallel processing system having an optimized total latency 26. Here, the optimization can be applied to the hardware infrastructure. The quantities important to the optimization are known in numerical form in matrices 151, ..., 15i for each time unit and each independent chain and branch: for example, from the contents of the matrices: (i) the number of basic instructions that must be sequential, (ii) the size of the data transfer from computation block x in computation chain u, and when this transfer is needed again on computation block y in computation chain v (if y > x) (for example, possible over a network or by combining computation blocks to place the data on the same cache line). For example, in the case of a GPU, data should be copied from memory to GPU memory in one process step, and then all basic instructions with the same properties should be executed at once. On a CPU, however, operations with the same data should reside on the same cache line (CPU dependent), or operations for a particular data type may be computed on the corresponding CPU which has the necessary better instruction set. In the system of the present invention, this always leads to parallel code without optimization, because the basic elements are grouped into sequential groups within the cache box.

[0091] In summary, since the (micro)processor understands only basic instructions, the source code 31 is divided into these basic instructions in order to achieve the most basic level of parallelization. (It should be noted that the present invention is also applicable to the technical problem of optimization, since the (micro)processor is based on the principle of an integrated circuit (IC), which is a set of electronic circuits. The aforementioned instructions are linked to the configuration of electronic circuits on the (micro)processor, and therefore the following topics are applicable to any form of integrated circuit, or conversely, since instructions can be seen as a form of configuration of electronic circuits representing computational operations (e.g., +, -, data manipulation, etc.), they can be used to derive an optimized integrated circuit (or configuration of electronic circuits or direct electronic circuits) for a given code.) The following core points are important to the system of the present invention: (1) The basic instructions of the processor system are combined according to their inherent "READ" and "WRITE" behaviors, i.e., form a chain of instructions according to the following rule: in a chain of nodes, "when an instruction writes to X1, a new instruction to read to X1 is appended after the last instruction to write to X1," and links to the computation block 333. (2) When it is necessary to propagate information / data in the multiprocessor system 2, a new compute block 333 is started. (3) Each compute block 333 has a minimum time length. This is proportional to the length of time (latency) required in the hardware system to propagate information (data or signals) to and from the block 333. (4) In the case of a graph model having two read data nodes, an instruction node, and one write data node connected by a link, the chain from compute block 333 has two chains that (a) have a meeting place (e.g., because an instruction reads from two data points to be written to two different compute blocks 333, or because a branch exists), and (b) have an origin place (e.g., where two compute blocks 333 can be started by reading simultaneously).If necessary, the graph model may be based on, for example, two or more read nodes and several write nodes, or several instructions may be combined into a single operation / instruction node. (5) These chains 34 can be decomposed, and instructions and necessary information transfers for each discrete time interval can be captured in a matrix. For example, each row is divided into columns (one column for time intervals) and contains independent instruction chains and information that needs to be transferred to others. Thus, these are tangible for automatic optimization processes, especially numerical optimization processes. This provides the basis for fully automatic parallelization of source code. Note that in this automatic parallelization system 1, the graph model is not only based on matrix or tabular representation, but also provides, among other things, a multidimensional nested tree structure of computation block graphs as task graphs associated with computation parallel chains 34, thereby allowing system 1 to evaluate properties that can be utilized for automatic parallelization, code optimization, scheduling of computation blocks 333, and even automatic cost estimation or automatic mapping to different architectures of the multi-processing system 2.

[0092] As stated, in the computation matrix, a cell containing a chain of instructions 34 is given by a sequence of computation block nodes 333 that form the chain 34, and in the transfer matrix, a cell contains transfer properties, i.e., necessary transfers to and from other computation block nodes 333. Note that transfer properties include what information is needed at another computation block node 333. Depending on the level of the target infrastructure, this may be resolved by classical compilation / processor control = transfers in the cache (classical compilers distribute data into registers and attempt to efficiently utilize the cache level by leveraging data locality), or it may be explicitly shared by shared memory and protected by locks, or it may be explicitly sent and received between different nodes in a cluster using, for example, a Message Passing Interface (MPI) protocol, or it may be sent and received by sockets for multicore inter-process communication (IPC), etc. Transfer properties can have any form of communication, from those handled by the processor (cache) to those explicitly made by communication patterns (e.g., IPC, MPI, etc., via queues). This makes the method of the present invention scalable to a wide range of platforms and / or infrastructures. Therefore, the transfer properties may include information such as sending data %1 (integer) to cell (1,7). Transfers and / or communications require a certain amount of time, which usually directly depends on the (transfer / communication) latency in a given system. Finally, as mentioned, note that in a given row of a computation matrix, the column cells contain a flow or sequence of instructions, and each column cell in a row contains one computation block node 333 in a sequence of computation block nodes 333, thereby forming a chain 34 for that particular row. However, in variations of a particular embodiment, each cell in a row does not necessarily have to contain a sequence or instruction. One or more cells in one or more particular rows of a computation matrix may be empty. This is also true for transfer matrices. Computation matrices and transfer matrices are usually equal in size, i.e., number of rows and columns.The computation matrix, as well as the matrix and transfer matrix, provide a possible technical structure for automatic parallelization.

[0093] Technically, the matrix builder connects compute block nodes 333 according to the program flow (e.g., Figure 35) and / or code 32 from the parser module 11. The program flow is represented by connecting compute block nodes 333 (similar to basic blocks), for example, when adding a new instruction (=operation node), a new compute block node 333 may be generated, where generally there are no clear dependencies (see Figure 21), and the new compute block node 333 is placed after another compute block node 333 or under a branch node. After all instructions have been added, it is possible to number each compute block node 333 along the program flow that forms the sequence of chains 34 thus generated. These numbers (block numbers) are equal to the columns of the matrix. Computation block nodes 333 with the same block number are distributed in different rows of the same column in the compute matrix.

[0094] Task and gamma structure / graph generation Up to this point, we have described how to group basic instructions from sequential source code (a list of serial instructions) into computation blocks (CBs = a list of instructions preferably executed in serial order) as defined herein, index the resulting groups, and extract groups of instructions for parallel execution, including the transfers required for execution on different computing units. This method is built upon a systematic perspective of modern computing platforms, which are still limited by the binary computation step. This fundamental concept of how mathematical operations such as +, -, *, and / are computed on a binary computing system, i.e., the digital processor 2102 / 2103, brings about several physical constraints and dependencies, such as: (i) a=b <op>(ii) In order to compute the statement c, bit patterns b and c, each representing a certain degree of precision (from integer to double precision), must be physically available to the binary computing unit at the moment of computation. transfer (iii) This Δ transfers This is at least an order of magnitude larger than sequentially computing several instructions on a single computing unit, i.e., a single processor 2102 or processor core 2103. The grouping results in the grouping of instructions within a compute block (CB) based on data dependency extraction. Each of these consists of a single chain of sequential instructions. All necessary data transfers between CBs are preserved. This configuration makes it possible to optimize and automatically parallelize source code processed on parallel computing units, i.e., processors 2102 and processor cores 2103, respectively, in a hardware-independent manner without programmer hints.

[0095] A variation of one embodiment uses the system and method in the middle end of an automated parallelization compiler (see Figure 84). The generated results can be given as a tensor or a graph, depending on the form of representation (see Figure 85). When the code is represented by a tensor (or matrix), it consists of compute blocks, each having a chain of instructions within its cells. Each row represents a set of instruction groups that can be computed independently of the grouped instructions in other rows in the same column. In a second matrix, the corresponding data transfers are collected between the instruction groups. Figure 80 also shows how tensor entries can be represented as a graph. Note that consecutive entries in a compute matrix belonging to the same conditions are based on the same read data, since CB A is placed in its row and column by the segment number as soon as possible after the read data becomes available in CB B, which has segment number A=B+1 (one CB corresponds to a potential transfer time). These consecutive segments can be called compute segments, and it is shown that consecutive CBs can be computed without needing any other information. If there is one edge between two gamma nodes, those gamma nodes can be combined into one gamma node (Γ 3a +Γ 3b =>Γ 3b ). This makes it possible to combine them into the same gamma node, since they are based on the same data in the same way as consecutive CBs on the same row, if they belong to the same branch node. Such a computation segment is by definition a computation block node 333, as it contains any sequence of sequential instructions that do not share any data dependencies. When applied to Fibonacci, this can be seen in Figure 85 and leads to a computation graph like that in V. Sarkar, "Fundamentals of parallel programming module parallelism". The display of comparison instructions in the "expanded" example is for illustrative purposes to show how the method applied to LLVM-IR in Figure 75 forms a gamma graph. Figure 30 shows how the method forms at least one consecutive sequence of CBs across different branch nodes while maintaining the program flow from the program call (indicated by main()) to the end of the program (indicated by return(0)). This can also be seen in Figure 85. Interpreting this gamma graph on a multithreaded platform means that each edge introduces a latency for context switching.

[0096] (a) Combine rows / CBs with tasks Similar to the indexed version, CBs that can be computed in parallel are in the same column, meaning they have the same segment number. It is possible to combine CBs that have the same segment number (see Figure 39). In this step, the instructions in the new compute segment are added together, and possible transfers between units are eliminated (see Figure 11). This affects the time it takes to compute CBs in parallel or serially.

[0097] Another representation is a form of computation or task graph, referred to herein as a “gamma graph.” The following distinctions are made: (i) The computation graph is used in relation to (see V. Sarkar, "Fundamentals of parallel programming module 1 parallelism"), where nodes consist of arbitrary sequential instructions in the realm of ideal parallelism. (ii) A task graph is a general graph that has tasks, regardless of how these tasks are formed (for example, as a computation graph, or in the sense of functions in the field of functional programming, or otherwise). (iii) A gamma graph is a graph in which each node is a single CB or a combination of CBs. A gamma graph is a task graph and, at its initial granularity, a computation graph. A gamma node represents a computation segment (see above).

[0098] Each node represents one or more CBs. In a row of the tensor representation (meaning one unit), if there are no entries for transfers between columns, the compute blocks can be combined into a single compute segment. For each row, a separate compute and communication sequence unfolds. A gamma node consists of at least one compute block node (CB), or a combination of several CBs having the same segment number and / or the same compute segment. Thus, as described below, the system and method of the present invention can obtain a physically-based unique dynamic task granularity of the code.

[0099] Furthermore, as a result of this decomposition, distinct segments for computation and communication are obtained in each row (see tensor representation) or node (see gamma graph). Corresponding parallel code can be generated from the gamma nodes (see Figure 87). Δt compute Δt is the computation time. transfer This is the communication / transfer time. Figure 87 shows the separate calculation section and the transfer / communication section. Calculation time Δt compute and communication / transfer time Δt transfer Neither of these properties is easily obtained, nor does it have to be fixed to the platform, but the ability to extract these two distinct properties from the code during compilation is a unique feature of this method. This allows for the optimization of the distribution of nodes (code chunks) to available compute units by using available frameworks, such as openMP, MPI, or others.

[0100] In summary, the present invention's automated parallelization method and system group and index instructions within sequential code, providing the code in the form of compute sections of the grouped instructions and resulting communication (data transfer) sections, which can be represented as tensors or graphs. Each compute section can be viewed as a task with corresponding transfers / communications to other tasks. The construction of tasks follows a fundamental physical-based principle: distributing data (bit information) across different computing units introduces transfers and reduces computation time. This is a method for generating physically-based data chunks of code at different granularities. The ability to combine only parallel CBs enables the generation of task graphs with different task granularities. The ability to generate such task graphs for a given code introduces new opportunities for automatically optimizing / parallelizing code for given hardware consisting of two or more computing units. Combined with a solution approach for solving job / task scheduling, which is a potentially NP-complete problem on parallel machines, the present invention's method is a general method for distributing code across homogeneous or heterogeneous platforms.

[0101] The granularity of each task is G = Δt compute / Δt transfer This can be expressed as follows. For example, see J. Kwiatkowski, "Evaluation of parallel programs by measurement of its granularity." Granularity is linked to the level of parallelism. Several levels of parallelism exist (see above). (a) Instruction parallelism: Instruction-level parallelism (ILP) provides very fine-grained parallelism and is utilized by analyzing instruction dependencies. ILP is also implicitly utilized by the hardware scheduler of the microprocessor, i.e., microcontroller. (b) Data parallelism: Many program operations apply to elements of larger data structures. Operations can be executed on parallel or distributed systems. (c) Loop parallelism: Loop iterations can be executed in parallel if they have no dependencies. If all loop iterations require the same execution time, the allocation can be easily performed by static allocation with a fixed number of iterations to each computing unit. (d) Task (or thread) parallelism, which defines more parallelism in the sense of functional parallelism. In greatly simplified terms, state-of-the-art compilers are based on ILP and to some extent on loop parallelism. Decomposing code into basic blocks is one of the first steps in a state-of-the-art compiler. A basic block (BB) is a sequence of instruction code without jump interruptions. This means there are no branches other than the entry and exit points (see Hennessy, John L.; David A. Patterson, Computer architecture: a quantitative approach, Elsevier, 2011). The method of the present invention extends the concept of basic blocks and, for each BB, extracts the possible parallel instructions and the corresponding transfer options between them and other BBs in the corresponding control flow graph (CFG).

[0102] The following illustrates how the concept of basic blocks interacts with the method of the present invention. Figure 88 schematically shows code in the form of BB and CFG. Figure 89 shows the corresponding graphical representation of potential compute blocks (CBs) after applying the method to the code. The grouping and sequencing of CBs depends on the instruction data dependencies within the BB. After indexing the CBs, the compute and communication segments are expanded into two units as seen in Figure 90. T and F indicate segments that depend on conditions leading to branching in Figure 89. This branching occurs when there is a possible parallel instruction opportunity to parallelize the compute in the BB, and the transfer time Δt can be seen in the first communication step in Figure 90. transfer It forms.

[0103] For each path (one possible order of nodes through which a code passes based on one specific combination of conditions), the corresponding transfer size S path1 S path2 and S data The following are extracted (see Figure 89). In the resulting parallel code, each branch transition or modification of a basic block has a corresponding transfer, depending on the possibility of instruction parallelism within each basic block. It is important to note that by combining CBs, these transfer properties may also disappear, resulting in an optimization problem that can be best optimized by a state-of-the-art compiler method targeting a single computing unit. Computation segments can be considered as tasks, and transfers can be considered as communications. Code or program code is a sequence of operations with a clearly defined total order, where parallelism can be expressed as a partial order. The computation graph used herein is called a directed acyclic graph (DAG), where each node is a chain of sequential instructions (=tasks) and the edges are order constraints. The automatic parallelization method of the present invention can, among other things, automatically extract a specific computation graph (CG) G from code (for computation graphs, see, for example, V. Sarkar, "Fundamentals of parallel programming module parallelism"). Several properties are associated with the computation graph G, where t runtime,p is the execution time in parallel, and P is the number of computation units. If the execution time time(N) is known and assumed to be an uninterrupted sequential computation, this does not depend on scheduling on parallel machines: • Total execution time of nodes within G: Work(G) = Σ node N in G time(N) • Longest path within G (critical path) -> Critical Path Length: CPL(G) • The most optimized (ideal) parallelism of a given computation graph G: Work(G) / CPL(G)

[0104] Regarding scheduling, that is, the action of distributing computation tasks to resources, knowledge of the length of each task and how they are linked to one another can be essential to satisfy those constraints and to schedule them optimally. This is especially true for symmetric parallel architectures, under the assumption that the computation time of the critical path (CB) is small relative to the transfer time. Here, the critical path (longest path in G = CPL) is an important property, as it is impossible to schedule the CG G to be computed or processed in less than this time, thus providing a measure of how well a given code can be parallelized.

[0105] When G is run on a parallel processor machine with P processors (independent of scheduling): (1) The capacity boundary is at least t runtime,p ≥Work(G) / P. This is because t runtime,p This means that a runtime of less than t is impossible on P processors (even if they are completely partitioned). (2) The critical path boundary is at least t runtime,p ≥CPL(G) / P. This is because each scheduler must follow the dependencies in the critical path, so if a particular code is t runtime,p This means that parallelization cannot be scheduled for runtimes less than t. Therefore, the runtime t in parallel is limited. runtime,p It is given by:

number

[0106] In summary, the system and method of the present invention provide a novel technical approach for extracting the computation graph of a given code. In EV3, this is also possible for loop sections without explicitly resolving all data dependencies between instructions. This enables new opportunities for automatic parallelization of source code to hardware, depending on its latency characteristics. The present invention demonstrates great potential, particularly when applied to the technical problem of loop-level parallelization, a central aspect of high-performance computing (HPC) applications, as loop sections can introduce large computational demands. Opportunities to utilize the highly optimized parallelization of the present invention are given particularly in applications where data is stored in random-access data structures. In this regard, well-known technical examples for benchmarking automatic parallelization are recursive or loop implementations that generate Fibonacci numbers, which will be discussed later. Furthermore, the automatic parallelization compiler can form a task graph as a function of a given transfer time (TT), assuming that parallel machines consider transfer time as overhead for executing applications in parallel (e.g., context switching in a threaded environment). In other words, the system of the present invention can provide special automatic parallelization that generates optimized parallel code optimized for hardware-specific characteristics in order to execute tasks in parallel on a parallel processing system used, in particular on a specific architecture of one or more multicore central processing units (CPUs).

[0107] (b) Transfer matrix elements and task computation length Generally, this method can be used to obtain a computation graph defined in the domain of ideal parallelism from code, compared to V. Sarkar's "Fundamentals of parallel programming module parallelism." This allows for the inference of several code properties when the execution time is known for all nodes with uninterrupted sequential computations, and when the assumption is applied that this time is independent of scheduling and there are no processor limitations. As mentioned above, knowledge of the length of each task and how they are linked to each other can be essential for optimal scheduling, i.e., the action of distributing computation tasks to resources, in order to satisfy their constraints and schedule them optimally, i.e., achieve the best optimization.

[0108] Measuring the clock speed frequency of processor 2102 or processor core 2103 or the performance and hardware-specific parameters of the parallel processor architecture is insufficient for the automated parallelization system 1 of the present invention, as more precise parameters exist that are necessary to measure performance. Today, it is important to understand that there are a considerable number of processor types and brands on the market whose hardware properties and characteristics differ significantly, such as Intel, AMD (Advanced Micro Devices, Inc.), and ARM (Acorn RISC Machines or Advanced RISC Machines). Each company has multiple different architecture types and processor tiers, which further complicates matters. For the best optimization of parallelization, a precise method is needed to compare the computing power of these processors. One possibility for measuring processor performance is to measure instructions per second (IPS). Therefore, today, IPS, typically measured in MIP (million instructions per second) or GIP (billion instructions per second), can be used as a measure of the speed of, for example, processor 2102 / 2103, and can be considered a general measure or benchmark of the number of instructions that processor 2102 / 2103 can process per second. However, in the case of complex instruction set computers (CISC), for example, different instructions take different amounts of time, so the measured value depends on the instruction mix. Even when comparing processors within the same family, IPS measurements can be problematic. Many reported IPS values ​​represent the "peak" execution rate in artificial instruction sequences with few branches and no cache contention, but realistic workloads usually lead to significantly lower IPS values. The memory hierarchy also significantly impacts processor performance and is a problem not adequately considered by classical IPS measurements. Therefore, there is no proper way to measure MIP, and MIP measurements cannot be used as a measure of the instruction execution speed required by system 1 of the present invention; at best, they can be used as a task execution speed compared to a reference.In summary, the speed of a given processor depends on many factors, including the type of instructions executed, the order in which they are executed, the presence of branch instructions (a problem in the processor pipeline), and different cache levels.

[0109] Note again that the processor instruction rate may differ from the clock frequency because some number of clock cycles may be required for each command to complete, or the processor may be able to execute multiple independent commands simultaneously. MIP can be useful when comparing performance between processors made with similar architectures (e.g., microcontrollers of the same microchip brand), but it is difficult to compare between different CPU architectures and the processor 2102 / 2103 architectures. In particular, MIP measurements with higher numbers are of little meaning for the real-world situation of the operation of this system 1 that requires accurate hardware-specific measurement parameter values. Regarding the processor architecture, the design process includes selecting an instruction set and a specific execution paradigm (e.g., VLIW or RISC), and usually results in a specific microarchitecture described, for example, in VHDL or Verilog. In the case of microprocessor design, this description is manufactured using some of the various semiconductor device manufacturing processes, and as a result, a die that is bonded onto a chip carrier is obtained. Then, this chip carrier is soldered onto a printed circuit board (PCB) or inserted into a socket thereon. The operating mode of any processor is the execution of a list of instructions. Instructions usually include those for calculating or manipulating data values using registers, changing or retrieving values in read / write memory, performing tests on the relationships between data values, and controlling the program flow. The clock speed of the processor described above is another measure that is generally measured in megahertz and gigahertz. However, again as described above, the clock speed itself is not an accurate form for measuring the processor performance of the present invention. Finally, FLOP (the number of floating-point operations that can be executed per second) is yet another factor for measuring the performance of a processor. A floating-point number is a number having a floating decimal point such as 0.008. However, the FLOP benchmark measures only floating-point operations and not integers, which means that the FLOP benchmark also cannot measure the processor performance alone.

[0110] Therefore, simply measuring the execution time of a single CB is neither effective nor practical. However, state-of-the-art compiler methods are constructed to optimize a given set of instructions on a processor and are NP-completely optimized. The system of the present invention does not change any instructions regarding the scale of how instructions are scheduled on the processor. In the system of the present invention, the relative computation time of CBs is far more important than the absolute computation time for a particular instruction or a single CB. The goal is to determine the relative durations of different CBs and to divide the computation time from data loading and storage (affected by the memory hierarchy, e.g., cache access), which is expressed as transfers in the method (for example, in a multicore architecture, data between computing units can be shared by L2 or L3 caches, and the optimization of the system of the present invention is to distribute CBs in a form where transfers occur on L2 / L3 caches). The code within a CB can be compiled into machine code using the state-of-the-art compiler method. Modern state-of-the-art compiler methods aim to leverage processor characteristics (primarily within the scope of the basic block) for a given set of instructions, such as leveraging instruction parallelism by using appropriate specific registers (e.g., XMM registers), using floating-point units, and out-of-order execution. This results in optimized machine code for the target compute unit. As mentioned earlier, there are established methods for determining the cycle duration of a single machine instruction as a function of the processor clock speed (see A. Fog, "Instruction tables", Technical University of Denmark, 2022). Based on these tabulated values ​​for these machine instructions and the available latency as a function of data size for the data hierarchy (e.g., cache level, memory, etc.), the relative duration for computed cycles (CBs) can be derived.The optimal use of single-instruction scheduling is thus covered by the well-known state-of-the-art compiler method, which is very well established and covers the NP-complete problem of scheduling instructions for a single computing unit / processor. Such a step also involves a set of arbitrary sequential instructions and the required data size S. comp The relationship is derived to compute this instruction set on given hardware. Along with the clock speed frequency, this allows for modeling the computation time difference between separate CBs (=sequential instructions). Since CBs in the same column represent a unique and distinct set of instruction chains with no data dependencies, the relative runtime can be approximated by the number of instructions, a specific number of cycles per instruction, and memory access. Note that instruction chains within consecutive CBs are always based on the same unique first "read" information (within a CB, the read value for the next instruction is located immediately after the definition of the write instruction = compute block node 333). Any other information required for computation in a CB is gathered by transfers in the transfer matrix. This fundamental property of data locality allows for deriving whether this data can exist on different memory hierarchies (cache, memory, disk, or network, etc.). This differs for combinations of CBs within the same column, for example, indicating available data dependencies by cache level. This effect can be detected by accumulating the data sizes of all parallel cache lines, which is the minimum size of data that needs to be loaded into a register, and from this, the latency to the corresponding cache level that can hold the information can be derived. Once the data is loaded in chunks (e.g., page size, cache line size, etc.), the minimum number of loads to a given data level can be derived and used to write parallel code with optimized data locality.

[0111] This method does not mean to provide a better approach for optimizing instructions on one processor, but rather to provide a structured method for utilizing across different levels (from ILP to LLP) and constructing physically-based chunks of instructions based on their data locality. Based on these separate instruction chunks (CBs), general optimization problems can be inferred and optimized for (a) with respect to the physical relationship (b) referred to as rel1: I. The method obtains a computational graph, and thus, for all levels within the graph, the maximum number of unique chains of parallel of any sequential instruction (CB) is known as a function of runtime parameters. II. The computational unit / processor has the following: i. A set of latencies for fetching data of a given size (where the data size conforms to registers, Ln cache, memory, disk, etc.). ii. For a given series of instructions, the minimum data size / input bit size S comp is required to compute a given series of instructions on a given processor or combinational circuit. iii. For a given series of instructions, a corresponding method for computing this series of sequential instructions (instruction set, processor architecture, cache and memory layout, or combinational circuit vs. sequential circuit) gives a separate computation time on the processor / combinational circuit.

[0112] This means that for all gamma graph levels, (a) the number of different CBs, (b) for each CB, the minimum size for computing the instructions within the CB, and (c) the necessary "read" and "write" data sizes represented as data transfers are known during compile time as a function of runtime parameters. An idle point (idl-point) represents a gamma node where the processor becomes idle (e.g., refer to return(0) in Figure 80), which is where Γ2 and Γ 3b for all S transfer,i of the transfers and problem size S comp,2 and S comp,2, and 3,a This indicates that the calculation may not be performed if the same runtime is not available. This information is extracted in a general form from any given code, since the data-related information must be in any form of executable code.

[0113] In summary, along a gamma graph with an initial granularity = computation graph, referred to as rel2 (see II above): (1) Each level gives the number of parallel gamma nodes. Each CB consists of a unique instruction chain (Figure 80: Γ2, Γ 3a Γ4) (2) Each node has a separate data size S required to compute instructions (variable type functions, processor properties, and available SOTA compilation methods) compute,CB Having with respect to a given platform (3) Unique transfers to and from gamma nodes

number

[0114] The same information is included in the tensor notation. S extracted by this method compute and S transfer a) Problem size per graph level (S total parallel computation size in parallel CB) compute =ΣS compute,Cb i a) a set of unique instructions that can be executed in parallel, c) S for all gamma nodes compute CB, i This gives the size required for the calculation of S. compute, CB, i This defines the minimum register size (or use of a higher memory hierarchy) on a given platform for computing a set of instructions within the CB, and, if the CB is viewed as a combinational circuit, defines a separate minimum area N required on the silicon wafer (N. Weste, et al., "CMOS VLSI Design, A circuits and systems perspective", Addison-Wesley, 2011). transfer By combining this, the number of loads to the fastest available memory hierarchy (memory, flip-flops, etc.) is known. These size properties are known by EV3 as functions of loop variables and loop header definitions. Based on this EV1, this method makes it possible to associate (1), (2), (3) (see rel2) with (i), (ii), (iii) (see rel1), and thus become numerically optimizable.

[0115] This forms the basis for a wide range of different optimization approaches for real-world applications, as the assumption of ideal parallelism does not hold true in actual applications.

[0116] Optimized scheduling for loop sections - loop-level parallelization Loop-level parallelization is one of the central aspects of high-performance computing (HPC) and high-performance technology computing (HPTC) applications, as loop sections can introduce large computational demands. HPC and HPTC utilize supercomputers and computer clusters to solve complex computational problems. In particular, with the increasing complexity of integrated circuit (IC) designs at the nanoterrascale, multicore CPUs and multicore GPUs have become ideal hardware platforms for emerging parallel algorithms. Today, multicore processors are widely used across many application domains, including general-purpose, embedded, networking, digital signal processing (DSP), and graphics (GPU). Core counts can reach tens, exceed 10,000 in specialized chips, and in supercomputers (i.e., clusters of chips), that number can exceed 10 million. To efficiently utilize such platforms, parallelization, especially optimized loop parallelization, is technically absolutely essential. However, one of the technical challenges of parallelization also stems from the fact that leveraging parallel hardware platforms at extreme scales beyond 22nm and 60GHz, where complex source code and algorithms such as circuit simulations exhibit strong data dependencies, is extremely difficult. The automated parallelization system of the present invention, in particular, provides the elimination of data dependencies in the parallelization of complex code, such as technical circuit simulations, e.g., parasitic extraction, transient simulations, and periodic steady-state (PSS) simulations, which paves the way for unlocking the underlying capabilities of parallel hardware platforms. The performance improvements obtained by using parallel processing systems such as multicore processors depend heavily on the level of parallelization achieved. In particular, the possible gains are limited by the proportion of parallelized code that can be executed in parallel simultaneously on multiple cores or processors, and this effect is explained by Amdahl's Law.In the best-case scenario, embarrassingly parallel problems can achieve acceleration factors close to the number of cores, and even faster if the problem is sufficiently optimized and divided to fit within the cache(s) of each processor or core, avoiding the use of much slower main system memory. In the prior art, most applications are not accelerated even with refactoring. The automated parallelization system of the present invention enables the achievement of the best possible optimization, eliminating data dependencies in the columns of the computation matrix.

[0117] Loop-level parallelization in computer architecture is complex. The technical objective of loop-level parallelization is to extract parallel tasks within a loop to speed up a process. This need for parallelism arises particularly when data is stored in random-access data structures such as arrays. A program executed sequentially iterates over an array, performing operations on multiple indices at once, while parallelized code with loop-level parallelism uses, for example, multitasking / multithreading / multiprocessing, where indices operate simultaneously or at different times. As mentioned above, opportunities to utilize parallelism primarily lie in applications where data is stored in random-access data structures. In loops, data dependencies can be categorized as follows: [Table 2]

[0118] The key difference lies in "loop-carried" versus "loop-independent" dependencies. In a "loop-independent" dependency, there are no dependencies between statements in each iteration. For example:

number

number

[0119] In this application, the following classifications can be used. (1) DISTRIBUTED loop: Statements that are not dependent can be extracted, calculated in a separate loop, and thus distributed. [Table 3] (2) DO-ALL parallelism (Independent Multi-Threading (IMT)): Statements can be extracted within a loop that can be executed independently. Therefore, all statements within the loop core can be executed independently. [Table 4] (3) DO-ACROSS parallelism (Cyclic Multi-Threading (CMT)): Statements or calculations that are executed independently and can be executed simultaneously can be extracted. [Table 5] (4) DO-PIPE parallelism (Pipelined Multi-Threading (PMT)): Parallelism is utilized when loop iterations are distributed across a synchronized loop. [Table 6]

[0120] Distributed loop parallelization is the simplest and requires no further explanation. In DO-ALL parallelization, all iterations of a loop are executed in parallel and completely independently, without inter-thread / inter-task communication, as in distributed loop parallelization. Iterations can be assigned to threads / tasks in a round-robin manner. The round-robin method is, among other things, a scheduling method for handling queues. For example, the round-robin method can be used as a process scheduler, which assigns limited execution resources to several competing processes, or in parallelization, to processing units as processors. The round-robin procedure allows all processes to be successively assigned to one or more execution units for short periods within a time slot. In the art, this process is also called arbitration. In parallelization, round-robin can be used, for example, to load balance processing units. DO-ALL parallelization and distributed loop parallelization are only possible if the loop does not contain loop-carry dependencies or can be modified so that contention does not occur between concurrent iterations during execution. Loops that can be parallelized by DO-ALL parallelization are likely to experience speedups due to the absence of inter-thread communication overhead. However, since many loops do not follow this form of parallelization, the lack of communication also limits the applicability of this technique.

[0121] In DO-ACROSS parallelization, iterations are allocated to threads / tasks in a round-robin manner, similar to independent multithreading. Optimization techniques described for increasing parallelism in independent multithreading loops are also applicable to cyclic multithreading. This technique involves the compiler identifying dependencies and delaying the start of each loop iteration until all dependencies from the previous iteration are satisfied. Thus, the parallel portion of one iteration overlaps with the sequential portion of subsequent iterations, resulting in parallel execution. Once all cores have started their first iteration, this can approach linear acceleration if the parallel portion of the loop is very large enough to allow full utilization of the cores.

[0122] DO-PIPE parallelization is a method for parallelizing loops with inter-iteration dependencies. Here, the loop body is divided into several pipeline stages, each pipeline stage assigned to a different core. Then, each iteration of the loop is distributed across the cores, and each stage of the loop is executed by the core assigned to that pipeline stage. Each individual core executes only the code associated with the stage assigned to it. However, there is no consistent method in the prior art for handling and automating loop-level parallelization, as currently provided by the system of the present invention, and certainly not at the level of automatic parallelization.

[0123] In compiler techniques, loops are represented, for example, in the case of a low-level virtual machine (LLVM), as different nodes in a control flow graph (CFG). It should be noted that the CFG, when used herein, is not only a graphical representation but also accurately represents the flow within a program unit, which is why it is used in compiler techniques and compiler systems. The effects of loop definitions and their influence on inductive variables during runtime often depend on runtime parameters. Since the location of the changes is known in the code, the “read” and “write” concepts of the systems and methods of the present invention can be applied to array expressions within loop bodies. Thus, the effects on array expressions that have dependencies on loop variables can be determined during compilation by distinguishing between different computation blocks (CBs), namely (1) reading data from a random-access data structure (e.g., an array), (2) computing a statement, and (3) writing data back to the data structure, as described above for basic blocks within one or more bodies of a loop section. This is shown in Figure 91, which illustrates a simple loop section within a control flow having a loop body with an LLVM IR code, showing how this leads to "read," "calculate," and "write" compute blocks (CBs) according to the method of the present invention. In a simple example of the form a[i+Δiw]=a[i+Δir]+C with Δiw=4 and Δir=0, the CBs within the loop (e.g., i=0~7) can be represented as shown in Figure 92.

[0124] As described above, the loop section can be represented by a gamma graph with parallel task nodes, where each task node is one or more combined computation blocks (n || ) and the number of correlated iterations (n loop ) has. Figure 93 shows such a loop section with parallel CBs and explicit loop iterations.

[0125] In this configuration, this method converts the body of the (nested) loop section into a DISTRIBUTED or DO-ACROSS / DO-PIPE loop parallelism setup. As mentioned above, there can be two different cases when building a gamma node from a (nested) loop section. • This is a general-purpose CB with case 1-1 read-write, which results in distributed loop parallelism. • This is a general-purpose CB with case 2-K read-write capabilities, which provides O-ACROSS / DO-PIPE loop parallelism.

[0126] Hardware parallel processing architecture with limited resources In the case of hardware parallel processing architectures with limited resources, the limited resources, i.e., the number of available computing units, n units <n || As a result, the gamma node is different from n units The optimization steps of the present invention's method for scheduling differ in the following two cases: • Case 1-1 - Read-Write Case: As shown in Figure 80, a gamma node connected to one edge (or a CB in one row with no entries in the transfer matrix and the same branch node) can be combined, meaning that the CBs again construct distinct "read" and "write" chains. Following the example in Figure 96, the loops are, at that level, each of length n loop n has || It is represented as n gamma nodes. Optimization for limited resources is performed using these n || The goal is to distribute the gamma nodes evenly. Since a gamma node is composed of CBs with sequential instructions, it is possible to divide a gamma node between any of the sequential instructions and split the gamma node into two different units (see Figure 103). In each unit, n evenCBs The remaining gamma nodes n are scheduled. partialCBs (n evenCBs ,n partialCBs )=divmod(n || ,n units These are then evenly scheduled across these units by adding transfers. This is beneficial as long as the latency added by the additional transfers is sufficiently smaller than the corresponding distributed computation. • Case 2 - k-read-write case: Optimization combines computation blocks (computations are summed up and transfers are discarded) to make n CBs available. units The goal is to distribute the data evenly among the individual units. In this case, the combination of CBs should minimize the resulting transfers.

[0127] Both optimization steps can be shown to be solvable by an analysis engine (i.e., a system based on at least arithmetic logic units, control flows in the form of conditional branches and loops, and integrated memory) under given assumptions. A method that solves a particular problem and can be processed within a finite time by a finite analysis engine is also called Turing-complete. In other words, the automated parallelization system and method of the present invention provides a Turing-complete system, with respect to a class of automated parallelization problems, since any automated parallelization of any possible source code is computable on the computing system by the method of the present invention. This is not true of all known prior art automated parallelization systems, and demonstrates the novelty of the system and method of the present invention in parallelizing loop sections during runtime, because this is the highest technical hurdle in prior art automated parallelization systems. In fact, it is important to note that the hardware architecture-specific optimized parallelization of source code achieved by the system and method of the present invention works not only for loop-level parallelization but is also generally applicable to source code parallelization. computation ga t data-transfer Assuming that t is small, the computation blocks within the columns of the computation matrix can be evenly distributed to form longer tasks that are distributed across parallel processing units / processors / cores. computation <t data-transfer Assuming this is the case, when variations of this embodiment are used, the number of CBs in a task can only vary by at most 1, so the number of CBs does not need to be evenly distributed among the parallel processing units / processors / cores available on a particular piece of hardware. This is true when all parallel processing units / processors / cores have similar performance characteristics and the same transfer latency.

[0128] As a variation of the embodiment, a “symmetric hardware platform” serves as the basis, where the source code is automatically parallelized by an automatic parallelization system to be hardware-specific and hardware-optimized. The symmetric hardware platform has computing units (processors / cores), all of which have approximately the same computing power and the same transfer properties as one another. This is often given, at least approximately, to the cores of a multicore CPU. In this setting, the method of the present invention enables the Turing-complete optimization of gamma node scheduling when the total computation time on one unit is not faster than the overhead of running the problem on two or more units. This is possible because all parallel CBs have the same computational demands and therefore the same computational effort, and all computing units can solve these computations simultaneously.

[0129] The present invention introduces a novel structure for how to handle (nested) loop sections in code in BB, and for a number of processing units n of a particular hardware architecture. units This further enables the construction of tasks accordingly. Since analyzing all data dependencies within a loop is impractical (i.e., using a brute-force approach by trying all possible solutions is not typically applicable to NP-complete problems such as loop parallelization), the method of the present invention is used to decompose or structure loop sections according to Figure 94. Thus, the system and method of the present invention makes it possible to form a gamma graph relying only on loop sections in a CFG having BB without unfolding and analyzing (brute-forcing) all correlated data relationships. The system and method of the present invention constructs a general loop structure formed from the CB of the loop sections.

[0130] When distributing the gamma nodes in a loop section to computing units, the following phases must be distinguished: (i) Initial phase: Data is retrieved from the location (computation unit) where the last write operation was performed before the loop started. (ii) Computation phase: n on a given computing unit || n parallel CBs loop times calculation (iii) Inner loop mapping phase: Transfer data for the next loop iteration on all participating computing units. (iv) Results phase: n on all computing units loop Once an iteration is complete, the data may need to be transferred back to the host.

[0131] Depending on the target platform, different sections can be shaped accordingly. For example, in a cluster configuration where locally stored data is stored on disk and synchronized by the file system, the resulting section does not need to be explicitly applied. Another example is in a multicore environment where data is shared in memory. There, the transfer is not explicit, but an internal loop mapping can be used as a barrier to avoid race conditions (see above). Figure 95 shows four phases as an example, where n units = 4

[0132] n || Since n is a function of the unique read and write constraints in a statement of the form a[i + Δiw] = a[i + Δir], the method of the present invention analyzes the array representation within the loop body to find the minimum read-write distance ΔI rw and thus derive n || . This must be possible because the array index must be within the range of the array definition and a positive natural number; otherwise, access to the array is impossible. In steps where the loop variable changes (is written) and must be retrievable in any code, the change in the index is analytically derivable during static compilation. This position in the code defines when this information is available at runtime and thus when the dependent parallel opportunities can be utilized. Once n || is known, the iterable loop variable limit n loop can be derived from the loop definition, and at compile time, the runtime parameters and the numerical relationships with n || and n loop can be extracted. The system analyzes the reads and writes of the array during static compilation and can generate a gamma graph as a function of n || (which can be a function of the loop parameters) and n loop , resulting in a distributed loop with n loop iterations (see FIG. 93). This can be done without resolving all data dependencies. n || and n loop depend on the loop parameters in most cases and are thus not known until runtime. If all parameters are known, the scheduling of gamma nodes can be optimized analytically at compile time. If the parameters are runtime-dependent, the scheduling can be resolved analytically at runtime using the system and method of the present invention on the defined symmetric platform. There are two cases for optimizing gamma nodes for the compute unit.

[0133] Case 1: General-purpose CB with 1-read-write If there is only one read-write dependency in the alignment formula (s), the corresponding gamma node has the form of FIG. 96, and as an example, a[i+3]=f(a[i]). There is no inner loop mapping phase, and the system 1 of the present invention provides DISTRIBUTED parallelism. The computational load of each gamma node [Number] depends on the loop parameters and is therefore, in most cases, runtime-dependent. However, [Number] can be calculated by simple arithmetic operations: n loop,dist , n loop,reminder =divmod(n tot , n ll ), where each gamma node receives the CBs grouped together into one gamma node as a CB connected to one edge (=transfer), and they construct any sequence of consecutive instructions n loop,i =n loop,dist +n loop,reminder,j , where j∈[n loop,reminder , otherwise j=0.

[0134] Case 2: General-purpose CB with K-read-write If there are K-read-write dependencies in the model CB, the corresponding gamma node has the general form illustrated according to the example of FIG. 97, and the example is a[i+5]=f(a[i],a[i-1]). There is an inner loop mapping phase, and the system of the present invention provides DO-ACROSS / DO-PIPE loop parallelism. Therefore, the system 1 and method of the present invention derive the following: [Number]

[0135] This allows for per gamma graph

number

[0136] Load balancing in the computation section on a symmetric parallel processing machine. n loops The runtime for performing one iteration of a repeatable loop having (n) is minimized when all uniform computing units have an equal amount of CB. This is because all parallel computing blocks (n) || ) means that they can be distributed according to a certain relationship, where G is a weight {w1, ..., w n This is a graph consisting of a set of independent nodes with}, where k is the number of available processors. Next, we compute the following:

number

[0137] In the above scheduling of real-time tasks on a multiprocessor system, the schedule must be at least the same length as the largest task, and it cannot be more efficient than keeping all processors continuously busy. Therefore, it is clear that the given computation time cannot be improved by any system. Number of parallel CBs n || This is Δt in internal loop mapping. comp And, Δt comm Initial granularity using necessary transfers having

number

[0138] Next, the optimization step performed by System 1 of the present invention distributes parallel CBs according to the relationship (see above) to the optimal task granularity G nunits The goal is to generate: (a)n || n CBs units The Δt is distributed to each computing unit and distributed approximately equally across them. comp To obtain (b) Particle size G nunits Minimize the transfer between gamma nodes having Δt comp Minimize

[0139] It should be noted that step (a) is a step that can be performed arithmetically by System 1 of the present invention, in contrast to step (b), in which System 1 must optimize the internal loop mapping. It will be shown below that this mapping can also be performed analytically by the system of the present invention by combining only the CBs that minimize transfers, since the transfers disappear when the CBs are combined on a single computing unit.

[0140] G nunits Internal loop mapping optimization for Combining parallel CBs with a gamma node (resulting in a granular G nunits (This occurs), transfers on the same unit are canceled, and the calculations are added together (see Figure 99). Using a very simple example, it can be shown that only a combination of one of the read / write distances minimizes the number of transfers between gamma nodes in each iteration of a repeatable loop (n loop This can be summarized as follows, as shown in Figure 100: • The number of read accesses (loads on the right side of a statement or within the IR) and reads can be extracted, and the number of read accesses is n shifts It is expressed as follows. • Number of transfers per CB: Since one write-read can be eliminated by optimizing so that it is performed on the same unit in the next iteration, n transfers =n shifts It is -1. S T The transfer size per CB using this method is the size of a single transfer:S transfer =n transfers ·S T In the example in Figure 101, the result is S transfer = 2·S T It will become. • Combined CB:S not aligned with read shift transfer,combo (n comb )=n comb ·n transfers ·S T • Combined CB:S according to read shift transfer,combo (n comb )=n transfers ·S T =const

[0141] As shown in Figure 101, n transfers Depending on the combination, any combination is fixed S transfer,combo This leads to n in one gamma node. comb When combining more than one CB, the readout is performed from the same computation unit in each iteration. Using the statement a[i][k]=a[i-2][k]+a[i+5][k], we can observe several interesting properties (see Figure 102). • Using T, size S T A single transfer can be marked, and this depends on the array type "a". If read-shift=-2 originates from the representation part ([i-2][k]) and read-shift=+5 is the result of the representation part (a[i+5][k]), then the loop iteration distance when loop-iteration-step-size (loop iteration step size) is 1 is n comb,const =max(read-shift)-abs(min(read-shift))=7. · n comb,const When combined into a single gamma node based on this, two boundaries, boundary A and boundary B, are unfolded. · n comb,const Combining more than one item does not increase or decrease the number of transfers. - Transfers across boundary A: min(read-shift): 2·S T - Transfer across boundary B: max(read-shift): 5·S T - Total number of transfers from gamma node to gamma node at boundary A and boundary B: S T,const = (2 + 5) · S T =7·S T A gamma node with one CB has two forwardings. T,1CB = 2·S

[0142] n comb >n comb,const In the case of n comb When combining individual CBs, as shown in 103, the number of transfers is constant S. T,const This can be the case. This effect can also be seen in calculations. In Figure 101, 1 <n comb >n comb,const Once a combination of ranges is found, the CBs must be combined according to the write-read distance, which leads to a linear increase in transfers.

[0143] General-purpose CB with scheduling-1-read-write for Case 1 In a 1-read-write case, resource n units If the number of nodes is limited, the number of gamma nodes is n units When distributing, it is possible that some parts will remain: (n full n partial )=divmod(n || ,n units ). In this case, n partial The number of gamma nodes is available n units It must be divided equally among (n full n partial This can be done by adding additional transfers as a function of ). Adding additional divisions is meaningful as long as the distribution of the partial CB by adding additional transfers does not become longer than without division. Since a gamma node (one or more CBs) contains any sequential instructions, the place to divide is Δt comp It does not have a significant impact, partial / n units It can be defined by n. For example, n units When a[i+3]=a[i] with =2, this leads to (1,1)=divmod(3,2), which results in adding one additional transfer by splitting one gamma node.

[0144] General-purpose CB with scheduling-K-read-write for Case 2 Resources are limited, (n full n partial )=divmod(n || ,n units )n partial If = 0, the computational effort can be balanced by minimizing transfers. Partial result n partial If >0 exists, it is not possible to schedule all units in a perfectly balanced manner. This leads to idle time for other units, and there is no way to balance this imbalance because all units have the same performance, all transfers have the same properties, and read shifts do not allow any transfers to be reduced.

[0145] Gap in nested loops Gaps in iterations occur when the starting value and / or iteration step size are not equal to 1 in a (nested) loop, and the read (or write) is from / to a gap. This means that in a data structure, some values ​​are never written into the loop, or some data is read from the CB before the loop at each iteration step (e.g., boundary conditions in a 2d heat equation). Figure 104 shows a structured data index and the resulting gap when it is not iterated over the entire array.

[0146] Gamma node mapping and indexing There are different approaches to performing the mapping. One is to use the expanded loop [0,n || This involves generating a global index for ], which can be generated for all nested loops marked as gaps, with a start size, end size, and inter-step size. Then, using the number of combined CBs per gamma node, the gamma nodes can be mapped to the global index, and the local data index can be computed. By obtaining unique elements at each gamma node, the communication links for each phase include: · Initialization • Boundary conditions (readout from gaps during the calculation phase) • Loop mapping · Results

[0147] These can be easily found by a computable array arithmetic step. Other options include using a bit array depending on the read shift for each gamma node, as illustrated in Figure 103, or computing a global index at boundaries A and B (see Figure 102). Another approach is a reduced iteration step n for each computation unit as a function of runtime parameters. loop This involves calculating [the value]. This is executable during runtime, and therefore makes it possible to use this method to optimize loop sections on a symmetric parallel machine during runtime based on a model built during compile time.

[0148] Further embodiments, modifications, and applications of the system of the present invention. As shown in Figure 106, known technical problems in the field of parallel processing can be solved by the system and method of the present invention. In particular, Figure 106 shows different embodiments EV1 to EV5 of System 1 of the present invention. EV1 in Figure 106 shows the basis for the most basic embodiment of System 1 and method of the present invention and all other embodiments, EV1 provides automatic parallelization of code by optimizing to minimize overall latency. If the optimization of automatic parallelization is limited by the number of available parallel processors (single-core 2103 and / or multi-core 2102), and (ii) the latency of memory access and data transfer between processors 2102 / 2103 is not insignificant compared to the processing time required to compute the compute block node 333 on processor 2102 / 2103, then the embodiment variant EV1 is based on several basic assumptions, among other things, the number of resources with a limited row dimension n units To reduce this, rows can be combined. This form of optimization (i) ensures that each transfer introduces a significant latency compared to the case where the transfers in the transfer matrix disappear.

number

number

[0149] Finally, Modification EV4 of the embodiment shown in Figure 106 (see also Figure 110) illustrates a system of the present invention used for optimizing integrated circuit (IC) or chip design, solving technical problems of electronic engineering in IC design by encompassing the logic and circuit design required to design integrated circuits, i.e., ICs. In particular, the IC design provided by Modification EV4 of the embodiment provides a digital IC design, which can be used to manufacture components such as microprocessors, in particular multicore microprocessors, field-programmable gate arrays (FPGAs), memory (cache, RAM, ROM, and flash architectures), and digital application-specific integrated circuits (ASICs). The IC includes miniaturized electronic components integrated into an electrical network on a monolithic semiconductor substrate by photolithography. The digital design achieved by Modification EV4 of the embodiment provides a highly optimized IC architecture with respect to logic accuracy, maximizes circuit integration density, and arranges the circuit so that clock and timing signals are routed most efficiently.

[0150] The following describes in more detail some applications of System 1 and Method of the present invention.

[0151] (i) Automated parallelization of source code for generating the Fibonacci series Figure 75 shows an example of constructing a CB from the instructions (CMP, SUB, ADD) seen in Figure 76, and is shown as a gamma graph in Figure 81. This is a representation of the recursive call f(3) of the code in Figure 75. Applying this method to a loop implementation of the Fibonacci series will yield a similar graph.

[0152] Different parallel processing implementations with different performance properties are known for generating and computing the Fibonacci series. Below, we show how the present invention applies to implementation forms using a) recursive function calls and b) loops. Both implementation forms exhibit different performance. To understand the processing problem, you can refer to, for example, https: / / www.geeksforgeeks.org / program-for-nth-fibonacci-number / . Below is an example of processing (source) code that generates the Fibonacci series using recursion.

number

[0153] Parsing the function code of the fib(n) declaration yields a pseudo-token language, and the function code of fib(n) is given by:

number

[0154] Figures 41 and 42 schematically illustrate a compute block node (CB) with operations and corresponding data nodes (similar to the tokens in Table 1 above).

number

[0155] The next step is to number the computation block nodes according to their call locations in the code. This yields a pseudograph schematically represented in Figure 43, and consequently, computation and transfer matrices as shown in Figures 44 and 45.

[0156] Figure 46 shows the result of combining the start and end communication cells in the transfer matrix, eliminating empty cells in the calculation matrix, and returning them to different code segments. Based on these code segments, code can be generated directly (as a compiler), or it can be returned to code and then machine code can be generated using a state-of-the-art compiler (as a transpiler).

[0157] To demonstrate the advantages the system and method of the present invention brings to compiling a recursive implementation using the Fibonacci series, the following sections describe how the method of the present invention maps and / or optimizes the code in a solution that is more parallel than the input code. As shown to optimize the code, it is a combination between rows, and the graph is shown by combinations of cbn within branch nodes marked as branch2b (see Figure 43), and their combinations are shown in Figure 48. Calling a function is a way of placing the computation block nodes in the correct positions in the matrix and applying the corresponding transfers, as shown in Figure 47. With this in mind, a recursive call to a function can be considered in the method of the present invention as a transfer of function parameters and result variables in the return statement in Figure 48, as well as "read" and "write".

[0158] Following the example of fib(4), Figure 49 step-by-step shows how the reduction of additional compute block nodes and transfers (since everything is on a single compute chain) results in more optimized source code.

[0159] The depth of this chain depends directly on the number n in fib(n). Since recursive calls can be detected very easily in the code, it is easy to avoid implementing recursive calls in all dimensions in the final application. For ease of understanding, Figure 50 illustrates this in a somewhat simplified manner. Step 4 shows the cbn for calls with "n=4".

[0160] The next step in Figure 51 shows the transfer that will take place (transferring the information of the last "write" to the data node to the location where the "read" from the data node occurred, and storing this information in the corresponding compute block node). Since all computations are on a single chain, the transfer disappears as seen in Figure 52. When all steps are resolved, this yields a program in the form shown in Figure 53.

[0161] Converting this back into code using matrix representation, we can see the following code as a result. This results in more efficient code than the original fib(n=4) implemented by Table 1 above. Compiling this code with a state-of-the-art compiler yields more optimized code than if this method were not applied.

number

[0162] Since information (function parameter param[i]) is transferred to the corresponding cbn within the branch node of the function declaration, and then the return value(s) are transferred to a[i], recursive calls can also be interpreted as array operations to which the method of the present invention applies (see Figure 54). This leads to a perspective also seen in partial differential equations. Implementations of Fibonacci series in this form are further referenced below. However, as the next step, the following paragraphs demonstrate the handling of partial differential equations, which largely involves the extensive use of nested loops and array operations.

[0163] (ii) Partial differential equation (PDE) According to this application, it is possible to derive computational and communication models for freely given discretized implementations of PDE by arranging operational nodes in the dependencies of “read” and “write” patterns and using rules to resolve dependencies that are not clear by transfer. The PDE of the 2D thermal equation is used herein, and the 2D thermal equation is given by:

number

number

[0164] Figure 55 shows a portion of the implementation in Python. Each entry in the array is a data node. Reading from an array index is an operation node in this method that has the data node of the index and the base address of the array. Array operations can be considered operation nodes with corresponding data nodes (see Figure 56).

[0165] As an example of a loop array having the array operation a[i+Δiw]=a[i], Figure 57 shows the corresponding computation block node. With this in mind, the initial block (Figure 55) can be represented in detail graphically as shown in Figure 58. All computations within the computation block (see Figure 55) are performed within the j loop. By using 1D array notation and applying the basic rules of this method, the schematic form of the computation block node within the loop is derived as shown in Figure 59.

[0166] An array read (e.g., u[k][i+1][j]) creates a compute block node, and metadata for transferring a value to this index is added to both the cbn of the “read” node and the cbn of the location where this data node was last written (e.g., a[k+1][i][j]). This leads to the fact that a statement such as the array operation in the j loop (Figure 55) results in five compute block nodes representing the “read” operation of the array, then a compute block node that computes the arithmetic solution, and then a compute block node that has written to the array at position [k+1][i][j]. This form of representation gives a schematic view to show more clearly how the method takes such array operations into account. This leads to the situation shown in Figure 60.

[0167] One of the most basic principles of the present invention is to find the last operating node A that "writes" to data node B, and then place a new operating node C after operating node A that "reads" from B. If it is not a clear 0-dependency or 1-dependency, add transfers to the compute block nodes containing operating nodes A and C, respectively. Thus a[i1]=a[i2] is a "read" to the data node with base address "a" and index "i2", and a "write" to the data node with base address "a" and index "i1" (see Figure 56). Thus, each loop creates a new compute block node with a "read" or "write" operating node and the corresponding transfer. The following scheme (Figure 61) can be derived.

[0168] As can be seen in Figure 61, the loop is visible, indicating that every loop traverse is a new compute block node on a new compute chain (row in the matrix). Unless a transfer occurs, empty compute block nodes and entries in the transfer matrix disappear, so these compute block nodes coexist (resulting in the same block or segment number in the numbering process step). If a transfer occurs, the CBN numbers will be different, and they will no longer be computed in the same step. As can be seen in Figure 62, an offset in the index of a "read" or "write" operation can cause a transfer between compute block nodes containing a "read" or "write" operation node.

[0169] The dependencies in "reading" and "writing" indices within a loop lead to the conclusions shown in Figure 63. When ΔI is less than 0, it indicates that the loop can be unfolded on the same number of compute block nodes as the length of the loop. The length refers to the number of iterations defined by the starting value "i0", the maximum v...

Claims

1. A symmetric automatic compiler system for hardware-optimized automatic parallelization of program code executed by a multicore or multiprocessor parallel processing system, wherein the parallel processing system has a plurality of processing units that simultaneously process instructions for data within the parallel processing system by executing the program code, and the automatic compiler system comprises means for converting sequential source code of the program code written in a programming language into parallel processing machine code that includes several instructions executable by the plurality of processing units of the parallel processing system, or for controlling the operation of the plurality of processing units. The parallel processing system comprises a memory unit including at least a main execution memory unit having multiple memory banks for holding data of at least a portion of the processing code, and a transition buffer unit having high-speed memory for storing the starting position of the processing code and a data segment having at least a branch instruction or jump instruction and / or memory references and data values ​​used, wherein the main execution memory unit provides a slower access time than the transition buffer unit. The execution of the processing code by the parallel processing system includes the occurrence of a waiting time, which is given by the idle time of the processing unit between the processing unit sending back the data after processing a specific block of instructions of the processing code for the data and the processing unit receiving the data necessary for executing a consecutive block of instructions of the processing code. The compiler system comprises a parser module for translating the sequential source code into code having a flow of basic instructions executable by the processing unit, wherein the basic instructions are selectable from a limited set of basic instructions specific to the processing unit, and the basic instructions for the processing unit include exclusively basic arithmetic and logical operations and / or basic control and memory operations. The parser module comprises means for partitioning the code of the basic instructions into compute block nodes, each compute block node consisting of the smallest possible segmentation of a sequence of basic instructions of the code that can be processed by a single processing unit, the smallest possible segmentation of the basic instructions characterized by a sequence of basic instructions framed by consecutive read and write instructions, the sequence being indestructible between consecutive read and write instructions by smaller sequences of basic instructions, the read and write instructions being necessary for the processing unit to receive data necessary for processing the sequence of basic instructions and to send back the data after processing by the sequence. The compiler system comprises a matrix builder for generating matrices from a computation chain separated from the code, the matrices comprising a computation matrix, a transfer matrix, and a task matrix, each column in the computation matrix comprising computation block nodes that can be processed simultaneously based on the executableness of read and write instructions for transferring data required for processing the computation block nodes, the transfer matrix comprising transfer and processing properties for each computation block node, the transfer and processing properties comprising at least the data size of the data to be transmitted and the identification of the source computation block node and target computation block node of the data transfer, and processing characteristics relating to one of the plurality of processing units, Tasks in a task matrix are formed by the matrix builder, and in the case of a compute block node, each associated with a different read, the task is formed by dividing the compute block node in the column of the compute matrix equally according to the number of the plurality of symmetric processing units, forming one task for each of the plurality of processing units for each column of the compute matrix, and dividing the remaining compute block node into at least a portion of the task based on a predefined scheme, and in the case of a compute block node having reads to which at least partially identical data is transferred, the task is formed by minimizing the number of reads uniformly or essentially uniformly across the processing units, and / or minimizing the integrated processing time uniformly across each of the processing units if it exceeds a predefined offset value, The compiler system includes an optimizer module that uses a matrix optimization technique to minimize the total occurrence latency by providing an optimized structure of the tasks in the task matrix, wherein each column of the task matrix forms a computation chain of one or more tasks that create an ordered flow of computation block nodes to be executed by one of the plurality of processing units, The compiler system includes a code generator for generating the parallel processing machine code for the plurality of processing units having an optimized total latency, based on the computation chain given by the optimized task matrix. A compiler system characterized by the following features.

2. The compiler system according to claim 1, characterized in that the parallel processing system is a symmetric multicore system and / or multiprocessor system having the plurality of processing units, and the symmetric multicore system and / or multiprocessor system is a system having a plurality of cores or processors, all of which are exactly or essentially exactly the same.

3. The compiler system according to claim 2, characterized in that the processor and / or core have the same memory architecture and technical processor characteristics.

4. The compiler system according to claim 3, characterized in that the aforementioned technical characteristics include having identical processor or core performance, with the same or essentially the same number of instructions processed per second.

5. The compiler system according to any one of claims 1 to 4, characterized in that the predefined scheme includes dividing the remaining compute block nodes by adding additional transfers for processing each compute block node.

6. The defined scheme for dividing the remaining compute block nodes by adding additional transfers is such that the latency added by the additional transfers is less than the corresponding allocated compute time, and =divmod(n || ,n units The compiler system according to claim 5, comprising distributing the remaining compute block nodes equally among the plurality of processing units by adding transfers, provided that ) is true.

7. The compiler system according to any one of claims 1 to 4, characterized in that the predefined scheme includes dividing the remaining compute block nodes by adding one compute block node to each task until there are no more compute block nodes left.

8. The compiler system according to claim 1, wherein the parallel processing system is an asymmetric multicore system and / or multiprocessor system having the plurality of processing units, the asymmetric multicore system and / or multiprocessor system is a system having a plurality of cores or processors, and at least some of the plurality of cores or processors have different performance characteristics, such as a different number of instructions processed per second.

9. The compiler system according to claim 8, characterized in that the computation block nodes of the columns of the computation matrix are evenly divided according to the number of processing units by adapting the length of the tasks assigned to the different processing units with respect to the performance of the particular processor or core, based on the instructions processed per second.

10. The compiler system according to any one of claims 1 to 9, characterized in that the source programming language is a high-level programming language.

11. The compiler system according to claim 10, characterized in that the high-level programming language includes C and / or C++ and / or Python and / or Java.

12. The compiler system according to any one of claims 1 to 11, characterized in that the transition buffer unit includes a cache memory module and / or an L1 cache.

13. The compiler system according to any one of claims 1 to 12, characterized in that the waiting time includes register access time and / or L1 cache access time and / or memory access time and / or I / O operation time and / or data network transfer time and / or processor configuration time.

14. The compiler system according to any one of claims 1 to 13, characterized in that at least two of the processing units have different basic instruction sets.

15. The compiler system according to any one of claims 1 to 14, characterized in that the arithmetic operations include operations such as addition, subtraction, multiplication, and division.

16. The compiler system according to any one of claims 1 to 15, characterized in that the logical operation includes several logical expressions such as equal to, not equal to, greater than, less than, greater than or equal to, and the following.

17. The compiler system according to any one of claims 1 to 16, characterized in that the control operation includes a "branching type" and / or a "loop type".

18. The compiler system according to any one of claims 1 to 17, characterized in that the compute block node is generated by creating the read and write mapping of the data node by the operation node by mapping the read and write interaction of the single instruction.

19. The compiler system according to any one of claims 1 to 18, characterized in that the computation block node is composed of connected operational nodes, and the operational node is configured as a chain having one or more input data nodes and one or more output data nodes.

20. The compiler system according to claim 19, characterized in that the compute block node is connected to the next compute block node or control flow node or one or more input data nodes and one or more output data nodes to form a chain.

21. The compiler system according to any one of claims 1 to 20, characterized in that each pair of computation matrices and transfer matrices is realized by forming a single numerical matrix and / or a multidimensional numerical tensor.

22. The compiler system according to claim 21, characterized in that the optimization of the numerical matrix is ​​achieved as tensor optimization.

23. The compiler system according to claim 21 or 22, characterized in that the optimization of the numerical matrix or tensor by the optimizer module is based on a dedicated applied machine learning structure.

24. A compiler system according to any one of claims 1 to 23, characterized in that each compute block node in a compute chain is numbered in accordance with the ordered flow of compute block nodes in the compute chain by assigning a block number to the compute block node, and in the compute matrix and transfer matrix, the block number of the compute block node is equal to the column of the matrix, and compute block nodes having the same block number are distributed to different rows of the same column.

25. The compiler system according to any one of claims 1 to 24, characterized in that, in the calculation matrix, each row includes a calculation chain of processing units, the cells of the calculation matrix include the calculation block nodes of the calculation chains, and in the transfer matrix, the cells include the necessary transfer properties between other calculation block nodes.

26. The compiler system according to claim 25, wherein the transfer matrix having the cells having the transfer properties includes at least what information is required in another compute block node.