551

Sequential computation was the simplest and most intuitive processing method for handling computational tasks. Contemporary servers and PCs, however, have gained the multi-tasking ability with multi-core CPUs. Under the circumstances, sequential computation cannot make the most use of the computational power the CPU offers. Thus parallel computing is the best choice for implementing complex computational tasks and processing big data using multiple threads, or even multicomputers.

## 1. Multithreaded execution with fork

Multithreading allows subtasks to have their respectively independent threads to compute concurrently during the implementation of a computational task. esProc uses the fork statement to execute multiple threads. Its usage will be illustrated through the following example:

 A B 1 \$(demo) select * from EMPLOYEE [Sales,R&D,Finance,Production] 2 fork B1 =A1.select(DEPT==A2) 3 =B2.minp(BIRTHDAY) 4 return B3

A1 retrieves data from the database table EMPLOYEE: A2 performs the multithreaded operation using fork statement to select from each department the eldest employee. When executed, A2 gets result as follows: During the code execution with multiple threads, fork statement is used to loop through the sequence parameter, and according to the length of the parameter sequence, it uses multiple threads running in parallel to execute the code block where fork statement resides. The result of every thread returned through the return statement from the code block will be concatenated into a sequence in the main thread. We can also use a result statement to return the result.

Though looking like a loop computation, the execution of fork statement is different from that of for statement. Loops specified in the code block of for statement is executed by a single thread, while for a fork statement, subtasks separated by the sequence parameter are allocated to multiple threads running in parallel for implementation.

In order to further understand the execution of each thread, in A2’s code block output function is used to output the execution information to the console:

 A B C 1 \$(demo) select * from EMPLOYEE [Sales,R&D,Finance,Production] 2 fork B1 >output(A2+”-begin”) =A1.select(DEPT==A2) 3 =B2.minp(BIRTHDAY) >output(A2+”-end”) 4 return B3

During the execution of A2’s code block information is output from B2 and C3, respectively as the computation stars and ends. The output result after execution is as follows: As can be seen from the output result, different subtasks can be implemented concurrently but some may need to wait for being processed when resources are available. System runs, distributes and controls the multiple threads of execution according to the CPU capacity. The computing time for each subtask is affected by its computation volume and the thread by which it is being performed. The implementation of subtasks with multiple threads differs according to different environments.

Multiple threads of execution can use multiple parameters. For example:

 A B C 1 \$(demo) select * from EMPLOYEE [Sales,R&D,Finance,Production] [Texas,Illinois,Ohio,Florida] 2 fork B1,[“F”,”F”,”F”,”F”],C1 =A1.select(DEPT==A2(1) && GENDER==A2(2) && STATE==A2(3)) 3 =B2.minp(BIRTHDAY) 4 return B3

A2 uses three parameters in executing multiple threads. The parameters will be sequentially matched for computation, i.e. [Sales,F,Texas], [R&D,F,Illinois], [Finance,F,Ohio] and [Production,F,Florida]. In this case, department, gender and state are specified for selecting the eldest employees. A2’s result is as follows: The parameters used in the multiple threads of execution must have the same lengths.

We notice that in the above code the genders specified for selecting employees from every department are same. So the corresponding parameter can be written as the single value, as shown in the following cellset:

 A B C 1 \$(demo) select * from EMPLOYEE [Sales,R&D,Finance,Production] [Texas,Illinois,Ohio,Florida] 2 fork B1,”F”,C1 =A1.select(DEPT==A2(1) && GENDER==A2(2) && STATE==A2(3)) >A1=B2 3 return B2

While a multithreaded operation is invoked, the single-value parameter will be copied by each of the multiple threads for using the same parameter value. By the way, the result statement at the code block returns a record sequence instead of a single record each time, so the result of A2 is a sequence composed of records sequences: Cell C2 at the code block updates A1’s data by modifying them into a record sequence, which is the result of the subroutine derived from A1. Check A1’s data after the code block is executed and we can find that they haven’t been modified at all by the code block holding the multithreaded operation. Actually subroutines executed with multiple threads will respectively duplicate the current cellset, thus they are mutually independent and do not influence each other, let alone updating data of the main routine.

The execution of multithreaded code appears similar to that of the loop code. Why should we use multithreading? The answer lies in the following comparison between them:

 A B 1 =file(“PersonnelInfo.txt”) 2 =now() 3 fork to(4) =A1.import@zt(;,A3:4) 4 return B3.select(City==”San Diego”) 5 =A3.conj() =interval@ms(A2,now()) 6 7 =now() 8 for 4 =A1.import@zt(;,A8:4) 9 >A10=A10|B8.select(City==”San Diego”) 10 [] =interval@ms(A7,now())

This example requires finding out data of employees coming from San Diego from the text file PersonnelInfo.txt. We’ll use multithreading from the 2nd to the 5th line and run loops from the 7th to the 10th line. Both B3 and B8 import data in segments during the computation. Note that fork to(4) cannot be simplified for multithreaded execution. We get the same results in A5 and A10: B5 and B10 get the estimated computing time the two methods spend: It can be seen that multithreading spends much less time than the loop thanks to a better utilization of CPU.

## 3.  Set reasonable number of threads

Since multiple threads of execution can increase efficiency, then will the performance be improved more significantly with more threads? Let’s make an experiment.

 A B 1 =file(“PersonnelInfo.txt”) 2 =now() 3 fork to(4) =A1.import@zt(;,A3:4) 4 return B3.select(City==”San Diego”) 5 =A3.conj() =interval@ms(A2,now()) 6 7 =now() 8 fork to(400) =A1.import@zt(;,A3:400) 9 return B3.select(City==”San Diego”) 10 =A8.conj() =interval@ms(A7,now())

Multithreaded program with 4 threads is executed from the 2nd to 5th line while another multithreaded program with 400 threads is executed from the 7th to the 10th line. A5 and A10 get the same results as those in the previous section.

Now let’s check their computing time in B5 and B10: As we can see, A8’s efficiency doesn’t increase in spite of using so many threads in multithreaded execution; on the contrary, the efficiency decreases. The computer has limited CPU capacity, but too many threads have to wait in queue for being executed and they also need to use some CPU resources. That’s why the efficiency lags rather than increases. In practice, good performance can be achieved with the number of threads being a little smaller than that of CPU cores.