## 3 Computation Model
### Many-Core Structure and Communication of the Sunway TaihuLight  
In the SW26010 heterogeneous many-core processor, each CG contains one MPE and one operational core array, which consists of 64 CPEs, an array controller, and a secondary instruction cache. Therefore, the parallelism of MPI exists only between the MPEs, and the computational tasks on each MPE need to be further divided into CPEs. Since each CPE has only 64 K of memory, the MPE cannot transfer the calculated data to the CPEs at one time. Instead, the MPE transfers part of the calculated data to the CPEs after the CPEs computation is completed, and the data is written into the MPE's memory. Then, we proceed to the processing of the next part of the computation data (Figure 4a). However, this will result in frequent data communication between the MPE and CPEs, which increases the time cost. In order to solve this problem, this paper adopts a double-buffer mechanism (Figure 4b, Table 1). Each time the computation data is transmitted, about half of the memory is reserved from the core. The next data are transmitted while the data are being calculated on the CPEs. After the computation is complete, we check if the data transmission is completed; if it is completed, the next computation is performed. The computation of one data part at the same time starts the transmission of the next data part at the same time, and, if it is not completed, the CPEs wait. The double-buffer model can effectively reduce most of the communication time to improve the computation efficiency. For the computation of the grid point migration part, the information of the eight neighboring grid points around the current grid point is required. However, the neighboring grid point is discretely stored in the MPEs memory and cannot be transferred to the CPEs memory by direct memory access (DMA) at one time; therefore, it leads to multiple accesses to the MPEs memory and a higher time cost. To solve this problem, MPEs adjust the grid point data of the current grid point's neighbor from discrete storage to continuous storage before the data are transmitted between the MPEs and CPEs. The MPEs are responsible for adjusting the storage each time when the data are being computed by the CPEs, and, therefore, no additional time is required (as shown in Figure 5). Figure 3: Data partitioning methods: (**a**) one-dimensional (1D) partitioning; (**b**) two-dimensional (2D) partitioning. _............... _do k = kmin, kmax if (mod((k-kmin),concum)+1.eq.slavecore_id) then \(j=jmin\) index = mod((i-jmin),2) + 1 put_reply(mod((i-jmin)+1,2)+1)=1! Read in the first batch of data  get_reply(index)=0 callthread_get(0,atmin,j,k), a_slave(imin,index), (imax-imin+1)*4, get_reply(index), 0, 0, 0) callthread_get(0,b(imin,j,k), b_slave(imin,index), (imax-imin+1)*4, get_reply(index), 0, 0, 0) do j = jmin,jmax index = mod((i-jmin),2)+1 next = mod((i-jmin)+1,2)+1 last = next! Read in the data needed for the next round of calculation if (j.lt,jmax) then get_reply(next)=0 callthread_get(0,atmin,j+1,k),a_slave(imin,next), (imax-imin+1)*4,get_reply(next),0,0,0) callthread_get(0,b(imin,j+1,k),b_slave(imin,next), (imax-imin+1)*4,get_reply(next),0,0,0) endif do while (get_reply(index).ne.2) enddo! Wait for the data required for this round of calculation to be read in do i = imit, imax c_slave(i,index)=a_slave(i,index)*a_slave(i,index)+b_slave(i,index)*b_slave(i,index) enddo put_reply(index)=0 callthread_put(0,c_slave(imin,index),c(imin,j,k),(imax-imin+1)*4,put_reply(index),0,0) do while (ptu_reply(last).ne.1) Enddo! waiting for the last round of data to be written back! the first round does not have to wait for the direct pass. enddo do while (ptu_reply(index).ne.1) enddo! waiting for the last batch of data to be written back enddo enddo! waiting for the last batch of data to be written back enddo!