High-Level Directives to Drive the Allocation of Parallel ... - CiteSeerX

1 downloads 0 Views 117KB Size Report
called starters; every object but the starters is created at run-time, in an explicit way. Starters objects are in charge of booting the application, by exchanging the.
Copyright 1997 IEEE. Published in the Proceedings of HIPS '97, April 1997 at Geneve (CH). Personal use of this material is permitted. However, permission to reprint/republish this material for advertising or promotional purposes or for creating new collective works for resale or redistribution to servers or lists, or to reuse any copyrighted component of this work in other works, must be obtained from the IEEE. Contact: Manager, Copyrights and Permissions / IEEE Service Center / 445 Hoes Lane / P.O. Box 1331 / Piscataway, NJ 08855-1331, USA. Telephone: + Intl. 732-562-3966.

High-Level Directives to Drive the Allocation of Parallel Object-Oriented Applications

Antonio Corradi

Letizia Leonardi, Franco Zambonelli

Dipartimento di Elettronica Informatica. e Sistemistica- Università di Bologna Via Risorgimento 2, 40136 Bologna - ITALY Ph.: +39-51-6443083 - Fax: +39-51-6443073 E-mail: [email protected]

Dipartimento di Scienze dell’Ingegneria Università di Modena Via Campi 212, 41100 Modena - ITALY Ph.: +39-59-378517 - Fax: +39-59-370040 E-mail: {leonardi, zambonelli}@dsi.unimo.it

Abstract The paper presents the Abstract Configuration Language (ACL) implemented within the Parallel Objects object-oriented parallel programming environment. ACL defines a set of directives that allow users to specify the allocation needs of his/her application components without being aware of the architectural details. ACL directives drive the allocation decisions of the run-time support, by adapting its general-purpose behaviour to follow applications particular allocation needs. The effectiveness of the ACL approach in increasing the performances of parallel applications is confirmed by a testbed application.

tools for dealing with the allocation problem. Static allocation tools take their allocation decisions before the execution of an application [13]: they extract from the application code all the information needed to build the application graph, assign the application a given number of processor and map it on the basis of a mapping algorithm. Dynamic allocation tools take their allocation decisions at run-time [10]: they dynamically monitor the application and, on the basis of the information obtained, decide about the allocation of the new entities that enter the system (remote creation) and, eventually, about the migration of already allocated ones [9,14]. A great limit of automated allocation tools is that they follow general purpose goals, such as load balancing [16] and do not act in respect of the particular needs of the applications: this may sometimes limit the performances achieved by a parallel application. For example, in the effort toward load balancing an automated tool could move far frequent communicating entities and cause an increase in communication latency. When the allocation of automated tools is not satisfactory, one might decide to sacrifice the transparency in order to attain higher performances. In the static allocation case, the user is given the duty of off-line studying its applications behaviour, detect where inefficiencies reside and what allocation could best fit its application [4]. In the dynamic case, the capability dynamically influencing the allocation of a parallel application, instead, can be provided by allocation directives to be inserted within the application code [1]. In both cases, to keep the environment usable and portable, the approach must be a high-level and architecture-independent one.

1. Introduction The allocation problem - i.e., the assignment of the components of a parallel application to the resources of a target architecture - is one of the key points to be addressed in the design of any parallel programming environment. A high-level parallel programming environment should be able to address the allocation problem, both in static and dynamic case, in the respect of two main requirements: transparency, i.e., the programmer should be made unaware of the allocation onto a given architecture and should concentrate only on the logical structure of its applications; high-performance, i.e., the allocation must try to minimise the application execution time. To provide full transparency, a parallel programming environment must integrate automated

The paper adresses the above problem in the dynamic case and presents the approach adopted in the Parallel Objects environment (PO for short). The PO model follows the guidelines of the object-oriented paradigm [17] and enriches it by the means of parallelism. The scenario of execution of a PO application is highly dynamic because of run-time object creations and dynamic passing of object references: neither the execution and nor the communication needs of resources of an application can be foreseen. Then, dynamic allocation tools are needed [9]. In PO, automated dynamic allocation tools are integrated within the run-time support and can manage the allocation of a PO application independently of any user intervention. In addition, a set of directives collectively called Abstract Configuration Language or, shortly, ACL - can be specified by the user at the application level to tune the behaviour of the automated allocation tool and let it meet the particular allocation needs of the application components. ACL allocation directives are abstract and portable, because they do not refer to any architecture-dependent detail: it is in charge of the run-time support implemented for a given architecture to make them assume a concrete physical meaning. In addition, ACL directives are defined at the class level and specify the allocation needs of the instance objects. That allows the user to characterise its applications by acting not at the level of the single application components, but at the level of the class property. The effectiveness of the ACL approach to improve the performance of parallel object-oriented applications has been validated via application examples. The paper is organised as follows. The PO environment and its allocation issues are described in section 2. The ACL language is presented in section 3. An application example, showing the effectiveness of the approach, is described in section 4. Related works are presented in section 5.

thread is associated with each object. PO expresses parallelism in two forms: the first form stems from the association of independent execution capacity with objects (inter-object parallelism); the second one from the definition of multiple threads of execution within the same object (intra-object parallelism). In PO, computation results from message passing between objects. When one object requires an external service, it sends a message to another object: the message specifies the service the client object needs. The server object verifies whether the operation is correct and executes the specified operation (a method, in the object-oriented terminology). Asynchronous and future modes of communication increase inter-object parallelism, decoupling sending and receiving objects. Intra-object parallelism is given by the presence of multiple execution activities (i.e., threads) within the same PO object. A parallel object can receive more requests: each is served by an internal activity (i.e., a thread). The consistency of the object state concurrently accessed by these activities is guaranteed by an a priori scheduling policy: an activity is created only if its pattern of access to the state does not conflict with the ones of already executing activities [6]. PO scheduling policies can be user-defined by means of high-level synchronisation constraints and are subject to inheritance. CLASS: INHERITS_FROM: INSTANCE_STATE: INSTANCE_METHODS: PRIVATE_METHODS: SCHEDULING_PART: ACL_DIRECTIVES:

This section describes the PO programming model and its allocation issues. PO is currently implemented on a massively parallel architecture, a Meiko CS-1, and on a network of UNIX workstations.

2.1 The PO Model The PO environment is based on the active object model [5]. This model provides independent execution facilities internal to each object: at least one execution

END_CLASS;

Figure 1. The template of a PO class PO objects are always instances of a given class. A PO class describes the interface, all the operations that can be requested to its instances, the state variables of an object, the synchronisation scheduling and the allocation directives (see figure 1 for a template

example of a PO class). The PO environment for distributed implementations adopts a solution with multiple copies of classes, one for each node where is executing an instance of the class. Since PO classes cannot change during execution, this is the most efficient solution. PO adopts its own language for the definition of the application classes, mainly inspired by Smalltalk. A pre-compiler is in charge of translating the PO description in an intermediate architecture-independent C representation that exploits the primitives made available by the PO run-time support. The analysis of the PO language issues, however, is outside the scope of the paper: we forward the interested reader to [6].

not only at the activity level but at the state level too: it is possible to partition the object state and distribute it onto several nodes. In this case, we talk of partitioned object. A distributed object can get advantage from having its state partitioned, because this permits its distributed activities to exploit locality in the access to the state.

3. The Abstract Configuration Language This section describes the main characteristics of the Abstract Configuration Language (ACL for short), presents several examples of ACL directives and shows how the ACL directives integrate with the run-time support to dynamic allocation.

2.2 Allocation Issues in PO The scenario of a PO application is highly dynamic. A first aspect of dynamicity, a intra-object one, comes from the servicing of the requests by a server object: every request implies the dynamic creation of a new thread of execution within the object. Objects themselves have dynamic nature: when a PO application starts, it is composed of some initial objects, called starters; every object but the starters is created at run-time, in an explicit way. Starters objects are in charge of booting the application, by exchanging the first service requests and eventually by creating new objects and request them some service. Moreover, every newly created object can create new objects in its turn and send them requests. As objects can be dynamically created they can be dynamically destroyed. In PO, objects and activities not only are dynamically created, but their allocation too must be dynamically decided at the creation time. The dynamic creation of objects requires the support to be able to manage it, by implementing remote creation policies and mechanisms, able to decide the allocation in dependence of the system state (i.e. the load of the system nodes) at the moment of creation. The PO environment also provides the possibility for an object to migrate [9], by moving it from a node (the sender one) to another (the receiver one), during its execution life. Migration can be useful to make objects follow the system evolution and it is suited to produce better load balancing than simple remote creation policies. When a PO object is completely allocated onto a single system node, it is said to be a concentrated object. The potential parallelism of the intra-object level can be transformed in real parallelism by distributing the internal activities of an objects onto several nodes. In this case the object it is said to be distributed. Moreover, object distribution is allowed

3.1 ACL Overview PO addresses the dichotomy between automated allocated tools and user-guided allocation with the definition of the Abstract Configuration Language. ACL is composed by a set of directives that specify the particular allocation needs of application components (i.e., objects and their internal components). The three main characteristics of ACL that make it a suitable user-driven approach to the allocation problem are [18]: • abstraction: ACL directives are not tied to particular characteristics of one kind of architecture; instead, they are abstract properties tied to the semantic of the applications; • definition at type (class) level: ACL directives are part of the description of a PO class; • interaction with the run-time support of the environment: ACL directives do not work in isolation but they influence the behaviour of an automated allocation tool integrated within the runtime support. The capability of maintaining ACL directives at an abstract level, independent of the architecture, the allocation directives is very important: depending on the target architecture, the run-time support is in charge of translating this abstraction into concrete “physical” terms. As an example, the locality concept (expressed in ACL by a “close_to” directive), can assume very different meanings: on a transputer based architecture, two entities can be considered close if they reside on the same node or on nodes that are directly connected by a communication link. In a network of workstations, because of the large difference in cost between internode and intra-node communication, closeness must be considered equivalent to coresidence. In a shared memory architecture with uniform memory access, the

locality concept loss its meaning and it is equivalent to “anywhere”. This abstraction level allows both the user to be unaware of any architectural details and applications to be portable across different architectures. The definition of ACL directives at class level allows users to not to focus on the allocation of single application components. Instead, users can consider the allocation needs of their application classes as part of their behavioural description. In addition, we claim ACL directives are specified in a section of the class separated from the functional description, thus granting a limited increase of complexity in the definition of a PO class. We also emphasise that the definition of the ACL directives at the class level could allow exploit the inheritance mechanism even in the allocation behaviour of a class. However, inheritance of the ACL directives is not yet implemented in PO. ACL has not been conceived to be the only allocation tools within the PO environment. By the means of the ACL the user can define the allocation needs of its allocation components but if integrated in an environment that provides automated allocation tools then ACL becomes a way of influencing the system allocation policy. The automated policy, conceived for general purposes goals such as load balancing, must act in agreement with the ACL directives, so to adapt its behaviour to the particular allocation needs of applications. It is clear that, depending on the user skill with the allocation problem, the ACL directive could be more or less constraining. At one extreme, the user can totally ignore ACL and let the allocation of the applications be completely decided by the system policy; since the system policy can not always act in respect of the application needs this might result in a lot of inefficiency. At the other extreme, the user can specify the application allocation needs in such a complete way as to almost (or fully) disable the automatic allocation policy: if the directives specified by the user are clever, they will realise “ad hoc” allocation policy for its application. Among these two extremes, all the intermediate cases are possible. Depending on the amount of ACL directives the user has specified in the definition of the classes of an application and depending on their imperative nature, the responsibility of the application is more or less in charge of the automated policy.

3.2 ACL Directives In the PO model, we have identified two levels of parallelism, the intra-object and the inter-object one. Their presence influence the allocation needs of a PO application and, consequently, ACL directives. We

distinguish between ###intra-object directives, that refer to the allocation of the components internal to an object (eventually in relation to each other), and ### inter-object directives, that refer to the allocation of objects and their parts in relation with the allocation of other objects. We are not interested here in laying a complete list of all the ACL directives. Rather, we want to clarify, by the means of several examples, their semantics and their interaction with the run-time support. Intra-Object Directives: In section 2.1 we have seen that, whenever it is beneficial, the internal concurrency within a PO object can become real parallelism by distributing the internal object activities onto several nodes. By default, a PO object is concentrated, being the atomic unit of allocation. It is possible to specify, in the definition of a class, the distributed() directive. In this case, the activities of the instances of that class are allowed to distribute themselves in a local environment. That means, for example, that in a transputer-based architecture objects could be distributed among five nodes (a central one and its four direct neighbours). We claim that the distribution directive does not automatically imply that all the instances of the class in which the directive is defined will be distributed objects. In particular, the run-time support provides object distribution only whenever it detects that such a distribution would provide benefits, in particular with regard to the load balancing purposes of the automatic allocation policy integrated within it. The definition of that simple ACL directive allows us to make us clarify some previous considerations: • ###the directive does not represent an imperative command. What the user specifies is that the objects of a given class could get benefits from real intraobject parallelism. Only at run-time, by the means of the dynamic allocation policy and the information it holds about the system state, it is decided whether the distribution is beneficial or not; • ###the directive applies to any architecture. However, on different systems, the concrete meaning it assumes could make it produce different effects. It is always possible to make to ACL directives assume imperative meaning, with a simple syntactic notation (distributed()!). In this case, the support interprets them as a command, whose execution is not related to the current system state. Only in case of physical impossibility (for example an object that cannot be distributed because of the lack of the necessary resources), the imperative directive is not issued. Imperative directives should be used sparingly, since reducing the interaction with the current system

state could lead to a bad exploitation of system resources. Another directive that can be specified at the intraobject level is the one that allow the migration (migratable()). Object can be subject of migrations during their life, and a default object behaviour could either allow or forbid objects to migrate. In the PO case the default is to forbid object migration: objects of given classes must be explicitly allowed to migrate by the means of the migratable directive. The migratable directive, again, represents a hint given to the support rather than a command. The allocation policy can load balance the system by taking into account the possibility of migrating only those objects that have been defined as migratable. Even if it is syntactically possible to give imperative character to the migratable directive, this is meaningless: object are migrated when in need of the load balancing policy. The presence of the parenthesis in the syntax of the directives lets suppose the possibility of parametrise them. In absence of any parameter, a default is assumed. Thus, we could have specified, in the distribution directive, a number of nodes onto which to distribute one object different from the default one (that is, the number of neighbour nodes). In the case of the migratable directive, the parameter, infinite by default, set the maximum number of times an object is allowed to migrate. Inter-object Directives The other class of ACL directives that can be specified in PO is the one that relates the allocation of the instances of a class (or of their parts) with the allocation of other application components. They represent mutual allocation properties. We distinguish several different mutual allocation needs that can occur among two components of an application: • co-residence (coresident() directive), when two components needs to share the same physical resources; • closeness (close_to() directive), when two components, because of intensive reciprocal communication, need to be allocated onto neighbour nodes; • neighbourhood (neighbour() directive), when two components with a high degree of communication need to be allocated close but not on the same execution nodes, so to allow them exploit real parallelism; Since the inter-object directives specify mutual property, one must identify the involved entities. One is clearly found as being an instance of the class in which the directive is defined. The other (partner), in relation

with the first, must be specified. The problem is that, because directives are defined at the class level, the partner must be identified before the creation of the instance itself. In an object-oriented environment, a reference to an object can be contained either in a state variable or in the parameters passed to a service request: this reference can be used to specify the partner. As an example, suppose that, within the instances of a class C, the state variable varX represents a reference to an object. A directive close_to(varX), specified in the class C, tells that any instance of the class C should preferably be allocated close to the object that is currently referenced by varX. Depending on the actual value that varX assumes, objects of the class C will be tied in a locality relationship to given partners. The same can be specified for the parameters of the operations. It is even possible, for a partner object, to be identified not by a reference to it but on the basis of its role with respect to the object that specify the ACL directive. As an example, every object is created by an activity of another object. The creator object could become the partner of a relationship specified in the class definition of the objects it creates. The directive coresident_to_creator(), for example, suggest the allocation of instance in the same node of the object that issues the creation request. Truly, every inter-object directive, when no parameter is specified, set as default parameter the creator object. While the neighbour() and close_to() directive leaves to the support some degree of freedom, in the choice of the nodes where to allocate an object respectfully of the directive, the co-resident directive force the allocation onto a specific node. In this case, giving imperative character to the directive could be meaningless, because it is already, in its semantic, imperative. Then, the difference between non imperative and imperative directives is relaxed: the system support tries, in any case, to respect them. However, an important difference still arise: when a directive cannot be respected (i.e., physical impossibility), a non imperative directive makes the execution continue, a imperative one raises an exception. Exception can arise from conflicting imperative directives too. As an examples, because of the values assumed by the references maintained by the application objects and used to specify ACL directives, the following situation could occur: • the instance I1 of the class C1 should be on the same node of the instance I2: that derives from having expressed a coresident(varX) directive in the C1 class and from having I1 set, at a current time, varX

to reference to I2; • the instance I2 of the class C2 should be on the same node of the instance I3: that derives from having expressed a coresident(varY) directive in the C2 class and from having I2 set varY to reference to I3; • the instance I1 and I3 should reside on neighbour node, in respect of the neighbour() directive expressed for one of the instances; The above conflict can be identified only at execution time, because it depends on the values assumed by the state variables of the instances. In case of imperative directives, an exception is raised; otherwise, the support is allowed to ignore some directive and continue its execution following its own allocation policy. As a general rule, the user should limit the use of imperative directives, so to avoid exceptions to be issued. All the above considerations about ACL directives refer to dynamic allocation. However, ACL directives (both intra and inter-object) can also be used during the initial mapping phase. In this case, ACL directives refers to the allocation needs of the starter objects in order to guide the mapping policy in allocating them.

application objects. It can decide either for a local creation, by delivering the message to the local creation manager, or for a remote creation, by sending the message to another allocation manager. In addition, the allocation manager can decide to migrate one object (or several objects). In this case, it sends to the object a request of migration: it is the object itself that manages its migration as an internal operation, since any external intrusion can be regarded as a violation of the OO encapsulation principle.

Service Requests

Application Objects

Monitoring Manager

Router Manager

LoadInformation

To/Fromother Allocation Managers

Allocation Manager

Object/Activities Creation Commands

Creation Commands

NewObjects (Components)

Creation Manager

3.3 Integration with the Support The support to the PO environment makes available automatic tools for both static and dynamic allocation [9]. Before the execution, a mapping algorithm is applied to define the initial allocation of the starter objects. The mapping strategy implements a parallel branch and bound search [7], that bases its search on the basis of information detected by the code at compile time and on the basis of the starter objects ACL directives, if any. During the execution, a set of entities, replicated onto each node and called system managers, provides the run-time support to dynamic allocation (see figure 2). The monitoring system manager periodically measures the application, in order to detect its evolution. The allocation system manager is in charge of deciding about the allocation of the objects in its node and bases its decisions on the load information provided by the monitoring tool of the node itself and on the load information of neighbour nodes [8]. More in particular, the allocation manager has to choose, toward the load balancing goal, the allocation of new objects (remote creation policy) and the migration of already executing objects ones (migration policy). The allocation manager intercepts all the creation messages sent by the

Figure 2. The PO run-time support The creation manager is the mechanism part of the dynamic load balancing tool. It implements the decisions taken by the allocation manager, i.e., it receives orders of creating objects in its node. This creation can involve either a “new” object, with no previously recorded state, or a migrated one, whose state comes from a previous execution. The interaction between objects and their parts is handled by the router system manager. It is in charge of the delivery not only of all messages that flow between the application objects but also of the ones between system managers of different nodes [3]. For a more detailed description of the PO run-time support see [9]. Of interest here is a description of the dynamic interaction between the run-time support and the ACL directives defined within PO class. ACL directives are dynamically managed by the allocation system manager. With regard to object creation, whenever the allocation manager receives one object creation request, the allocation manager controls if there are ACL directives specified for the object of that class. When no directives are defined, the allocation manager behaviour is not influenced and it can create the object by following its load balancing purpose. In the currently

implemented policy that means that the object is created in the less loaded node of the neighbourhood [9]. In the case a directive is defined that leave no freedom of choice to the allocation manager, it simply forwards the creation request to the creation manager of the specified node, without being involved in any decisional process. When a directive somehow leaves a choice to the allocation manager, the less loaded node among the ones permitted by the directive is chosen as target node for the new object creation. The allocation system manager can also detect the needs of migrations, from a sender to a receiver node, in order to obtain better load balancing. Even in this case the decision of the allocation system manger must take into account ACL directives. In particular, the identification of the objects to migrate onto the receiver node must be carefully evaluated [16]. This decision is taken by discarding, as subjects of migration, those objects whose ACL directives, at the decision time, are not compatible with the allocation on the receiver node. First of all, objects that are not allowed to migrate are discarded; then, objects that are in a relationship (and depending on the tightness of that relationship) with objects on the sender node; and so on, until objects that can get advantages (or cannot be damaged) from the migration are found. We claim that such analysis does not increase the complexity of the identification phase, instead, it tends to diminish it. In fact, when a lot of objects are allocated on a sender node, and in absence of any allocation hints, it could be difficult and expensive for the allocation manager to decide which objects to migrate and, often, this decision might not be a good one. In presence of the ACL constraints, the sorted list derived from them makes the decision faster and more effective. The allocation manager also manages the allocation of the components of distributed objects. If the objects of a given class are, as by default, concentrated, they are always allocated onto a single node. Then, after the creation, the allocation manager intervention is no longer needed. When the ACL directives specify that an object has to be distributed, it is in charge of the allocation manager to decide where and when to distribute its components, following the same guidelines of object creation. ACL directives are specified at the class level. In a pure object-oriented model, classes are objects themselves. Then, a creation request is considered as a service request to the object class of the instance to be created. ACL directives can be considered as the specialisation of the default behaviour of the class (the automatic allocation policy) in response to a creation request. The state of the class, that makes actions

depend on it, is the state of the system nodes. Analogously, one can interpret the migration policy as an operation that is in continuos execution within the class: it tests its state (the load of the node) to decide for the suitability of migrations. When a migration is found to be necessary, objects are chosen among the ones allocated on the node, on the basis of the ACL directives, and the “migration” service request is sent to them.

4. Application Example A simple testbed application implemented on a transputer-based architecture shows the use of the ACL directives and the increase in performances they permit to achieve. The implemented application models a simple parallel data base. The objects that compose it belong to two classes: a class Client and a class Server. The objects of the Server class hold in their state the tuples of a relation, making available to the object of the class Client the read, insert and update operations. Client objects call these operations of Server objects to access given tuples. With regard to the ACL directives, let us consider firstly the intra-object level. Server objects can be, during a given period of time, subject to a high number of service requests, so to heavily load the node onto which they are allocated. Then, if the server objects are not allowed to distribute onto more nodes, service response times worsen and the whole application execution is slowed down. Thus, it can be useful to specify the distributed() directive within the Server class, to allow server objects to execute their activities in parallel and to provide a quicker reply to the client objects. However, the allocation manager does not always distribute the server object activities, but only when this is beneficial. For example, when the server object loads its node of residence only lightly and does not make it overloaded with respect to the neighbour ones, no benefits would come from distribution: remote activities would be subject to even worse response time. Only when the server objects activities make the node overloaded with respect to the neighbour nodes the activities of the objects are distributed by allocation manager. During a set of experiments, we have observed that permitting Server objects to distribute their activities onto a neighbourhood of nodes never worsen the Server response time and, instead, it often reduces it of a 50-60 %. By moving at the inter-object level, client objects can require several services to the server objects, and

allocation manager, by issuing object migrations, does not break any particular locality connection. When increasing the average number of requests to the same server, instead, the inability of the allocation manager of taking into account the application communication needs results in a degradation of the performances. 140 120 server response time(ms)

often several services in sequence to the same server. In these cases, it can be useful to keep a client and the server object it is currently using as close as possible to each other, so to decrease communication latency and improve the service response times. The server that a client is using at a given time can be dynamically identified from a state variable holding the reference to it. Then, the directive close_to(), accepting that variable as parameter, can be used to suggest the allocation manager of keeping the allocation of the client local with the currently accessed server. Because the reference to the server object can dynamically change, the allocation need of any client object can change too. Then, it is useful to associate to client objects the migratable directive, that allows them to move in the system by always pursuing communication locality with the server objects. However, migrating one object as soon as its communication needs change can dramatically worsen the application execution efficiency, for two reasons: • clients objects that refer many objects for a short time period does migrate continuously, and that can make migrating objects waste a lot of system resources and can slow down object execution; • the load could become highly unbalanced, because of the presence, in restricted part of the system, of server objects heavily used by many clients. This problem is not present in PO because the allocation manager migrates objects only when it is beneficial for load balancing purposes. The close_to() directive influences the allocation manager because, when migration is worth, the object(s) to be migrated is (are) chosen among the ones, on the sender nodes, for which a migration on the receiver improve the locality with its current server. That way, objects can even be allocated far from their current server, but it is guaranteed that every migration action not only improve load balancing but also move some object closer to its server. Figure 3 shows the server average service time of the Server objects in dependence of the average number of request that client objects directs toward the same server: this is an index of the locality of reference within the application. Three different cases are reported: no load balancing tool applied at all (NLB, no migration and random remote creation), the automated load balancing tools applied without any ACL directives (LB) and the automated load balancing tools applied both with the above described ACL directives (LB+ACL). The performance improvement due to the load balancing tool only is relevant when client objects refer to the same server only for a short while: in this case the

100 80 NLB

60

LB

40

LB+ACL

20 0 10

20

30

40

50

# of consecituve requests

Figure 3. Average service time (milliseconds) of the server objects The presence of ACL directives to be evaluated by the allocation manager, is intrinsically overheading. Thus, in presence of little locality of references, the close_to() directive does not result in any real benefit and, instead, makes the average service time increase. However, as soon as the client objects refer for a longer time to the same server, the allocation manager can effectively exploit the ACL directive so to achieve, in its decisions, both load balancing and locality of communication. This results in a great improvement of the average service time of the server objects. The same qualitative results apply when varying the average system load, i.e., the global number of client and server objects.

5. Related Works Several object-oriented systems and programming environments exist that integrate automatic tools for dynamic allocation [13]. In Orca [2], for example, not only remote creation and migration is automatically managed by the system, but replication too The problem of inserting allocation directives within the application code in order to increase the performances of an application has been faced by the Emerald system [11] and by the Trellis/DOWL [1] one. In these systems, co-residence directives on related

objects and migration directives allow the user to specify in the application code the mutual locality needs of interacting objects. This occurs, as in PO, in abstract terms, without need of knowing the physical details of the target architecture. However, those approaches differs from the PO one: the run-time support is not capable of any “intelligent” filtering of the allocation directives and considers them as imperative commands to be executed. The current system state is not taken into account but in case of physical impossibility of meeting a directive. In addition, in those systems, allocation directives are mixed with the functional code of an application: to our personal opinion, this is likely to increase the complexity of the application. An approach more similar to the PO one is adopted in reflective object-based systems [12, 15]. In these systems, each application object is associated with a user-defined meta-level object, whose code can define the behaviour of the object in terms of its allocation. As in PO, such an approach permits to clearly separate the functional code from the allocation code. Moreover, meta-level objects can coexist with automated allocation policy. A characteristic of the approaches adopted by reflective systems is that meta-level objects, instead of defining a limited set of behaviours (as ACL directives does) are programmable entities and are allowed to dynamically exploit, in their code, a large amount of information about the state of the system. As a consequence, these approaches are more expressively powerful than the PO one. However, it is our feeling that this increased expressiveness lowers the programming level and makes the definition of the allocation behaviour too complex.

6. Conclusions and Future Work Fully automated allocation tools cannot always attain high-performances because they are unable to take into account, in their decisions, the particular allocation needs of the applications. The paper addresses the above problem and presents the approach adopted in the Parallel Objects object-oriented parallel programming environment to permit a user a high-level and portable customisation of the allocation of his/her applications. PO defines the ACL language, composed by a set of high-level directives, with which the user can specify the behaviour, in terms of allocation, of his/her application objects. ACL directives guide the allocation decisions of run-time support, by adapting its generalpurpose behaviour to follow applications particular allocation needs. In addition, ACL directives are abstract and portable, because they do not refer to any

architecture-dependent detail. The effectiveness of the ACL approach in increasing the performance of parallel applications is confirmed by a testbed application. Future work will deal with the implementation of tools to assist users in finding the appropriate ACL directives for their application classes and in evaluating their effectiveness. In addition, we are currently studying the problems that arise when making ACL directives subject to inheritance.

References 1.

B. Achauer, “The DOWL Distributed Object-Oriented Language”, Communications of the ACM, Vol. 36, No. 9, pp. 48-55, Sept. 1993. 2. H. E. Bal, M. F. Kaashoek, “Object Distribution in Orca using Compile-Time and Run-Time Techniques”, Proceedings of OOPSLA '93, ACM SigPlan Notices, Vol. 28, No. 10, Oct. 1993. 3. M. Boari et al., “Adaptive Routing for Dynamic Applications in Massively Parallel Architectures”, IEEE Parallel & Distributed Technology, Vol. 3, No. 1, pp. 6174, Spring 1995. 4. D. Bruschi et alii, “A User-Friendly Environment for Parallel Programming”, 1st EUROMICRO Workshop on Parallel and Distributed Processing, Gran Canaria (E), IEEE CS Press, pp. 451-456, Jan. 1993. 5. R. S. Chin, S.T. Chanson, “Distributed Object-Based Programming Systems”, ACM Computing Surveys, Vol. 23, No. 1, pp. 91-124, March 1991. 6. A. Corradi, L. Leonardi, “PO Constraints as Tools to Synchronise Active Objects”, The Journal of ObjectOriented Programming, Vol. 4, No. 6, pp. 41-53, Oct. 1991. 7. A. Corradi, L. Leonardi, D. Vigo, “How to Map Parallel Objects onto Transputer”, Proceedings of Transputer '92, Besançon (F), Sept. 1992. 8. A. Corradi, L. Leonardi, F. Zambonelli, “Load Balancing Strategies for Massively Parallel Architectures”, Parallel Processing Letters, Vol. 2, No. 2&3, pp. 139-148, Sept. 1992. 9. A. Corradi, L. Leonardi, F. Zambonelli, “Dynamic Load Distribution in Massively Parallel Architectures: the Parallel Objects Example”, Conference on Massively Parallel Computing Systems, Ischia (I), IEEE CS Press, pp. 318-322, May 1994. 10. Concurrency Practice and Experience, Special Issue on Resource Management in Parallel and Distributed Systems: Dynamic Scheduling, Vol. 7, No. 3, Oct. 1995. 11. E. Jul et alii, "Fine Grained Mobility in the Emerald System", ACM Transactions on Computer Systems, Vol. 6, No. 1, pp. 109-133, Feb. 1988. 12. H. Masuhara, “Study on a Reflective Architecture to Provide Efficient Dynamic Resource Management for Highly Parallel Object-Oriented Applications”, Master Thesis, University of Tokyo, Tokyo (J), Feb. 1994.

13. M. Nuttal, “A Brief Survey of Systems Providing Process or Object Migration Facilities”, ACM Operating Systems Review, Vol. 28, No. 4, pp. 64-79, Oct. 1994. 14. M. G. Norman, P. Thanisch, “Models of Machines and Computation for Mapping in Multicomputers”, ACM Computing Surveys, Vol. 25, No. 3, pp. 263-302, Sept. 1993. 15. H. Okamura, Y. Ishikawa, “Object Location Control Using Meta-level Programming”, European Conference on Object-Oriented Programming '94, Bologna (I), pp. 299-319, July 1994.

16. N. G. Shivaratri, P. Krueger, M. Singhal, “Load Distributing for Locally Distributed System”, IEEE Computer, Vol. 25, No. 12, pp. 33-44, Dec. 1992. 17. P. Wegner, “Concepts and Paradigms of Object Oriented Programming”, ACM OOPS Messenger, Vol. 1, No. 1, pp. 7-87, Aug. 1990. 18. F. Zambonelli, C. McHale, “How to Control the Allocation of Parallel Applications: a Survey on Tools and Language Constructs”, DEIS Technical Report No. DEIS-LIA-96-004, July 1996. Available at http://wwwlia.deis.unibo.it/Research/TechReport.html.

Suggest Documents