Translate this page:
Please select your language to translate the article


You can just close the window to don't translate
Library
Your profile

Back to contents

Software systems and computational methods
Reference:

Object-transactional Extension of Cilk++

Pekunov Vladimir Viktorovich

Doctor of Technical Science

Software Engineer, JSC "Informatika"

153000, Russia, Ivanovskaya oblast', g. Ivanovo, ul. Tashkentskaya, 90

pekunov@mail.ru
Other publications by this author
 

 

DOI:

10.7256/2454-0714.2022.3.38823

EDN:

LBFDUK

Received:

22-09-2022


Published:

08-10-2022


Abstract: In this paper, we consider the problem of developing compact tools that support programming in dynamic transactional memory, implying operational generation of transactional pages, for the Cilk++ language. It is argued that such an implementation requires weakened transaction isolation. The current state of the problem is analyzed. It is noted that the existing solutions are quite cumbersome, although they allow you to work with complex data structures such as lists and trees. It is argued that it is necessary to develop new solutions in the style of minimalism based on the use of specialized classes (generating transactional pages; implementing consistent transactional variables) in combination with a set of keywords characteristic of Cilk++.   Appropriate new solutions are proposed. New syntax elements are introduced, implemented using language extension tools specific to the Planning C platform. The semantics of new language elements is described. It is noted that, unlike analogues, the developed tools allow declaratively to "build" transactions into a network (network schedule of work), which determines the order of execution of transactions and the potential for parallelism that exists at the same time. The proposed approach was tested on the example of the task of constructing a histogram. It is also mentioned about the successful solution, using the developed tools, of the problem of training an artificial neural network by the method of error back propagation and the problem of integer linear programming by the method of branches and boundaries.


Keywords:

programming language, dynamic transactional memory, object-oriented programming, class library, syntactic constructions, language extension, managing the order of transactions, software transactional memory, Cilk++, transaction network

This article is automatically translated.

IntroductionCurrently, parallel programming is a fairly common activity for the average programmer, which is explained by the widespread use of multi-core processors.

This fact determines the existence of a long-term trend towards the development of various simple language tools for parallelizing sequential programs. In particular, such parallelization based on transactional memory is very promising, which does not (ideally) require explicit input of synchronizing constructs [1, 2].

At the same time, approaches based on the ideas of dynamic software transactional memory [3] are of considerable interest, allowing transactions to be generated dynamically, relying, for example, on the concepts of object-oriented programming. A transactional object implements a set of transactions, its fields, which are, for example, inheritors of special classes, are consistent variables. Other fields and ordinary variables are not consistent, realizing, in fact, some useful weakening of the principle of transaction isolation [4, 5].

The disadvantages of the implementations of this approach known to the author [3, 6] are: a large amount of additional code (not only launching and finalizing transactions, but also gaining access to a consistent variable, explicit handling of the failure of such access). This fact is probably due to the requirement of the possibility of parallel transactional processing of complex, for example, list data, however, there is a mismatch with the original idea of transactional memory, implying that parallelization of a sequential program does not require the input of any synchronizing constructs and significant processing of the program.

The disadvantages of existing approaches determine the need to develop new, simpler and more compact software tools for working with dynamic transactional memory (for example, focused mainly on processing classical scalar variables and arrays), this task is relevant. At the same time, approaches in the style of Cilk++ are of considerable interest, where, in the minimal version, only three keywords are introduced into the programming language (cilk_spawn, cilk_sync, cilk_for).

So, the purpose of this work is to simplify parallel programming in the conditions of dynamic software transactional memory. To achieve this goal, we will set the following tasks: a) expand the syntax and semantics of the Cilk++ language by introducing constructs for starting and waiting for transactions (the task in this formulation is new); b) propose a special class system containing at least a class that starts a group of transactions and classes of transactional (consistent) variables; c) implement the proposed mechanisms in Cilk++ for example, using the language extension tools offered by the Planning C environment for this.

The theoretical partThe development of the Cilk++ approach seems promising, consisting in extending the action of the keywords cilk_spawn and cilk_sync not only to functions (classic Cilk++), but also to objects of special transactional classes, which leads to the generation of a new transaction by the object (cilk_spawn) or to waiting for the completion of all transactions started by the object (cilk_sync).

There can be an arbitrary set of such objects (and, accordingly, transaction packages). At the same time, an approach is quite appropriate in which an unambiguous sequence of their complete execution can be established for individual transactional pages (from the start and, including all restarts, up to the final undelivered session), eliminating the need for additional constructs to explicitly synchronize the start of transactions. This can be achieved if cilk_spawn returns the identifier of the launched transactional page T and, in turn, can have as arguments a set of preconditions — identifiers of transactional pages that must be completed before the start of the page T.

We will develop two special template transactional classes, TObj<Class_A> and TQueuedObj<Class_A>, which perform the functions of launching groups of transactions in dynamic mode (the TObj<Class_A> class implements the launch with failures if a certain predetermined maximum number of transactions is exceeded, and the TQueuedObj<Class_A> class in such cases puts the transaction launch in a queue). If an arbitrary Class_A has fields that are instances of special template classes TArray<type_b>, TScalar<type_c>, then the classes TObj<Class_A> and TQueuedObj<Class_A> acquire the properties of dynamically launching transactions with consistent variables of types TArray<type_b> (from a programming point of view, equivalent to arrays with elements of type B) and TScalar<Type C> (from the programming point of view, they are equivalent to simple variables of type C), and all other fields and variables are inconsistent and the isolation principle does not apply to them. At the same time, cilk_spawn and cilk_sync are methods of the TObj<Class_A> and TQueuedObj<Class_B> classes and are able to run, encapsulating an arbitrary function or method of an object in a transaction.Syntax

Let's propose an extended syntax for dynamically starting a transaction:

[variable id "="] [object id ("."|"?>"|".*")] "cilk_spawn" ["(" number of conditionals"," identifier of conditionals ")"] "identifier of function_or_ method" "(" arguments")" ";"

arguments = [argument {"," argument}]

argument = constant | variable | "=" variable

Here, the object identifier is the identifier of an object of the TObj<class> or TQueuedObj<class> class or their successor (if the construction is launched inside a method of one of the listed classes, then the object identifier can be omitted, then the current object will be used).

This construct returns a non-zero integer identifier of the running transaction or zero if the transaction could not be started temporarily (this is only possible for TObj<class> objects and their descendants). The precondition array, if specified, contains the identifiers of the preconditions, that is, those transactions that must be completed before the start of this one. As for the arguments, special attention should be paid to the case of passing a local variable – if there is a danger that the transaction will end later than the current local block, then the variables declared in it should be passed with the prefix "=", which will create internal copies of such variables.

Now let's look at the extended syntax of the construction of waiting for the completion of all transactions started by the object:

[object_id ("."|"?>"|".*")] «cilk_sync» «;»;

Here, the object_id is also the identifier of an object of the TObj<class> or TQueuedObj<class> class or their successor.

ApprobationThe proposed syntactic innovations were implemented using the tools for building language extensions of Planning C. The corresponding deductive macros cilk_spawn and cilk_sync were developed, and a library of transactional classes and variables was written.

As a simple example of application, consider the construction of a histogram. Here, the main working class is Histogrammer, the process method of which performs useful work on processing one element of the source array (for which a histogram is being built). The matched variable is a field – a virtual array F representing an array of frequencies.

The transactional class is, respectively, TQueuedObj<class_Histogrammer>, on which transactions are started, within each of which the process method with specific parameters is executed. The same class also waits for the completion of all transactions when calling cilk_sync.

#include <stdlib.h>

#include < iostream >

#include <omp.h>

using namespace std;

#include "transacted.h"

const int N = 10000;

const int M = 600;

const int NF = 20;

class Histogrammer {

public:

         TArray< int > * F;

         Histogrammer(int nthreads) {

                   F = new TArray< int >(NF);

                   *F = 0;

         }

         void process(int * A, double grain, int i) {

                   int k = A[i] / grain;

                   if (k >= NF) k = NF - 1;

                   ++((*F)[k]);

         }

         ~Histogrammer() {

                   delete F;

         }

};

int main() {

        int * A = new int[N];

         srand(184415);

         for (int i = 0; i < N; i++)

             A[i] = rand() % M;

         double grain = 1.0 * M / NF;

         TQueuedObj< Histogrammer > obj(omp_get_num_procs());

         for (int i = 0; i < N; i++)

                   obj.cilk_spawn obj.process(A, grain, =i);

         obj.cilk_sync;

         int SF = 0;

         for (int i = 0; i < NF; i++)

                   SF += (*obj.F)[i];

         cout << SF;

         delete[] A;

         return 0;

}

This program is successfully executed, giving as a result the number "10000".

Also, using the proposed tools, the following were successfully solved: a) the problem of parallel training of an artificial neural network of direct propagation (modification of weights and calculation of the response of each individual neuron were separate transactions; transactions had preconditions reflecting the necessary sequence from execution) and b) the problem of integer linear optimization by the method of branches and boundaries (with the generation of transaction variants solutions).

Conclusions

So, in this paper, for the first time, an object-transactional extension of Cilk++ was proposed and implemented, which allows working with dynamic transactional memory. The developed tools are distinguished by the minimalism of the set of designs, as well as the ability to determine the order of transaction processing using launch preconditions (as a result, you can, for example, build a network transaction schedule). The implementation is based on extension tools specific to the Planning C language. The developed tools have been successfully tested both in solving simple problems (building a histogram) and in solving more complex problems of training an artificial neural network and solving the problem of integer linear optimization by the method of branches and boundaries.

References
1. M. Herlihy and J. E. B. Moss. (1993). Transactional memory: Architectural support for lock-free data structures. In A. J. Smith, editor, Proceedings of the 20th Annual International Symposium on Computer Architecture. San Diego, CA, May 1993, pages 289–300. ACM, 1993.
2. Marathe, V.J., Scherer, W.N., Scott, M.L. (2005). Adaptive Software Transactional Memory. In: Fraigniaud, P. (eds) Distributed Computing. DISC 2005. Lecture Notes in Computer Science, vol 3724. Springer, Berlin, Heidelberg. https://doi.org/10.1007/11561927_26
3. Herlihy, M., Luchangco, V., Moir, M., and Scherer, W.N. (2003). Software transactional memory for dynamic-sized data structures. In Proceedings of the twenty-second annual symposium on Principles of distributed computing (PODC '03). Association for Computing Machinery, New York, NY, USA, 92–101. https://doi.org/10.1145/872035.872048
4. Miculan, M., Peressotti, M. (2020). Software Transactional Memory with Interactions. Proceedings of the 21st Italian Conference on Theoretical Computer Science, Ischia, Italy, September 14-16, 2020, pp.67-80.
5. V. Luchangco and V. J. Marathe. (2011). Transaction communicators: Enabling cooperation among concurrent transactions. In Proceedings of the 16th ACM Symposium on Principles and Practice of Parallel Programming, PPoPP ’11, pages 169–178, New York, NY, USA, 2011. ACM.
6. Marathe, V.J., Spear, M.F., Heriot, C., Acharya, A., Eisenstat, D., Scherer III, W.N., and Scott, M.L. (2006). Lowering the Overhead of Software Transactional Memory. Dept. of Computer Science, Univ. of Rochester, March 2006. URL: https://www.cs.rochester.edu/u/scott/papers/2006_TR893_RSTM.pdf

Peer Review

Peer reviewers' evaluations remain confidential and are not disclosed to the public. Only external reviews, authorized for publication by the article's author(s), are made public. Typically, these final reviews are conducted after the manuscript's revision. Adhering to our double-blind review policy, the reviewer's identity is kept confidential.
The list of publisher reviewers can be found here.

The article submitted for review is devoted to the use of multicore processors, parallel programming and the object-transactional extension of Cilk++. The research methodology is based on the generalization of scientific publications on the chosen topic, the programmatic implementation of the proposed approach in the Planning C programming language. The relevance of the work is due to the spread of the use of multicore processors, parallel programming and the desire to simplify it in the context of the use of dynamic software transactional memory. According to the author, the disadvantages of existing approaches determine the need to develop new, simpler and more compact software tools for working with dynamic transactional memory. The scientific novelty of the reviewed study, according to the reviewer, lies in the development and software implementation in the Planning C language of the object-transactional extension Cilk++, which allows working with dynamic transactional memory, characterized by a minimalistic set of designs and the ability to determine the order of transaction processing using launch preconditions. The following sections are structurally highlighted in the article: Introduction, Theoretical part, Syntax, Approbation, Conclusions and Bibliography. In the introduction, the relevance of the study is substantiated, its purpose and objectives are formulated. Further, promising directions for the development of the Cilk++ approach are outlined, an extended syntax for dynamically launching a transaction is proposed, and a feature of the proposed design is outlined. The author defends the expediency of using an approach in which an unambiguous sequence of their complete execution can be established for individual transaction pages, eliminating the need for additional constructs to explicitly synchronize the launch of transactions. During the testing, the proposed syntactic innovations were implemented using Planning C language extension tools, deductive macros were developed, and a library of transactional classes and variables was written. The bibliographic list includes 6 sources – publications of foreign authors in foreign journals on the topic of the article. The text contains targeted references to literary sources confirming the existence of an appeal to opponents. The following points can be noted as comments. Firstly, it is hardly necessary to limit ourselves to generalizing publications exclusively from foreign sources, given that there are many works in domestic scientific journals devoted to multiprocessor computing systems and parallel programming. Secondly, the author claims that using the proposed tools, the problems of parallel training of an artificial neural network of direct propagation and the problem of integer linear optimization by the method of branches and boundaries were solved, however, these developments are not given in the text, references to the author's already published works on this issue are also not indicated. The reviewed material corresponds to the direction of the journal "Software Systems and Computational Methods", has been prepared on an urgent topic, contains theoretical justifications, elements of scientific novelty and practical significance.