In esProc Parallel Computing: Multithreading, we learned how to increase efficiency through executing multithreaded computation. But besides using fork in the cellset code to achieve the multithreading type of parallel processing, esProc also builds the approach of parallel processing into some functions. Let’s find out things about this in the following part.
1. Parallel data retrieval
We can retrieve data from data tables through multithreaded processing, if the order of records is irrelevant to the computed result. This type of processing can make full use of the system resources, thereby enhancing the efficiency. Add @m option to certain functions to use the parallel multithreaded processing. The functions include CS.conj@mx() and f.import@m().
Let’s start from the case where we retrieve data using the sequence of file cursors:
There are four text files in which ordering information of different kinds of products are stored. We want to retrieve all the records of product ordering into a sequence of file cursors, concatenate and summarize them. We use two methods to count the total number of orders. From line 3 to line 6, the cursors in the sequence are simply concatenated, thus records will be fetched in order. From line 7 to line 10, we use CS.conj@mx() to concatenate the cursors. In this way data will be fetched from cursors via multithreads; each cursor in the sequence uses an independent thread and these threads for record retrieval run simultaneously.
A12 compares the two methods to find how long it takes each of them to do this. The result is as follows:
We can see obviously that the multithreaded processing using @m option uses much less time and has a higher efficiency.
But the results of counting total number of orders in A3 and A7 with two different methods are the same:
Despite the same result, the two methods retrieve records in different orders. After the computations are finished, we can see in B5 and B9 respectively the 10,000 rows last retrieved. Now we compare them:
With the first method, data is fetched from every cursor in the sequence in normal order, so the last 10,000 rows in B5 come from the last data file Order_Books.txt. While with the second method of fetching data through parallel multithreaded processing, the returned data comes from every cursor. Therefore, in B9 data includes ordering information of every kind of product, the order in which it is fetched is irregular and data is mixed.
In spite of the higher efficiency we can get by retrieving data using parallel multithreaded processing, we can only use the method in computations whose result sets are irrelevant to orders, like summarizing and counting, because of the irregular order in which records are retrieved.
The parallel multithreaded processing also applies to cases where data is imported from a single data file, as shown below:
A2 imports data directly; while A3 uses f.import@m() to import data with multithreads. A4 compares the time the two methods use and gets the following result:
Importing data in parallel can significantly improve performance.
While a single data file is being retrieved with multithreads, the multithreaded system will divide the file into multiple segments and every segment will be retrieved with a file cursor. These file cursors use separate threads during data retrieval, which resembles the case where multithreaded data retrieving was done in the above example. For more information about retrieving data by segments in esProc, read esProc External Memory Computing: Binary Files.
Likewise, because multithreads are used while retrieving data from a single data file by parallel processing, the order of records in the result is irregular too. This can be proved by comparing results of A2 and A3:
With f.import@m(), the number of threads it uses is determined by the pre-specified Parallel number of task. Set this parameter in General page by clicking Tool>Option on esProc’s menu bar:
If the cellset program is run on parallel servers, the number of threads can be set through callxTask – the number of parallel tasks. For details about the setting, please see esProc Parallel Computing: The Server>.
2. Joining cursors
Parallel computing is used more than to improve the computational efficiency. It is a necessity for handling particular operations, for instance, joining cursors in a sequence together. Related functions include CS.pjoin() and F.cursor().
First let’s look at the case where file cursors in a sequence are joined:
Every cursor in A1, B1, A2 and B2 constitutes a column in the result. A3 generates a new cursor using CS.pjoin(). To fetch data from the new cursor, data from every cursor must form a record. B3 fetches the first 10,000 rows as follows:
In this case, retrieving data from A3’s cursor requires that every cursor containing a column of data needs to play a role concurrently. In other words, only multithreads can do this processing. esProc automatically employs multithreaded processing to join cursors, without the need of adding @m option. The number of thread it uses is determined by the length of the cursor sequence.
The same thing will happen when retrieving data from binary files stored in columnar format:
In A3, each column in the cursor is composed of data from a binary file. Similarly, every file will be retrieved as a cursor to be handled through parallel processing. The process is the same as that in the previous example, so is the result of B3.
3. Merging cursors in certain order
There is an operation that specifically requires parallel processing. That is merging cursors in certain order, i.e. CS.merge@x(). For example:
A3 merges the ordering data from four text files by dates and generates a new cursor.
During merging cursors in certain order, we need to judge which cursor the data should be fetched from according to the sorting expression, whenever necessary. This means cursors should be in place simultaneously throughout the computation, which is a problem also need to be approached by multithreading. Equally, esProc provides automatic use of parallel processing for this kind of situation, namely, no need of @m option.
B3 fetches the first 10,000 rows as follows:
If you want to learn more about the topic, please see esProc External Memory Computing: Merge and Join Cursor Data.