Academia.eduAcademia.edu

Towards reconfiguration and self-adaptivity in S-Net

2008

Stream processing is a well-suited model for parallel programming, as it allows the programmer to design parallel algorithms intuitively by arranging computational tasks into a data-flow graph and consecutively constructing a streaming network from it. However, a network that was designed with a specific workload in mind will not work optimally if anticipated parameters, as for example data rates or computational costs per data item, change over time. To nonetheless achieve optimal performance, a restructuring of the network and re-implementation of computational components is inevitable. As the deployment of a revised network usually causes service disruption, we present a system that supports reconfiguration of streaming networks at runtime. The reconfiguration of networks can either be triggered externally, i.e. initiated by the user, or from within the network itself (self-adaptation) by, for example, monitoring certain runtime parameters. Our system is based on S-Net, a coordination language for asynchronous stream processing systems. S-Net supports the simultaneous use of computational components implemented in a range of programming languages and it offers network combinators to construct streaming networks from these components. We will introduce S-Net and extensions of the language that allow for reconfiguration and self-adaptation of networks at runtime. The extensions are designed as network combinators and integrate seamlessly into the existing language.

UvA-DARE (Digital Academic Repository) Towards reconfiguration and self-adaptivity in S-Net Penczek, F.; Scholz, S.-B.; Grelck, C. Publication date 2008 Document Version Submitted manuscript Published in 20th International Symposium on the Implementation and Application of Functional Languages (IFL 2008) Link to publication Citation for published version (APA): Penczek, F., Scholz, S-B., & Grelck, C. (2008). Towards reconfiguration and self-adaptivity in S-Net. In S. B. Scholz (Ed.), 20th International Symposium on the Implementation and Application of Functional Languages (IFL 2008) University of Hertfordshire, School of Computer Science. http://staff.science.uva.nl/~grelck/publications/PencSchoGrelIFL08.pdf General rights It is not permitted to download or to forward/distribute the text or part of it without the consent of the author(s) and/or copyright holder(s), other than for strictly personal, individual use, unless the work is under an open content license (like Creative Commons). Disclaimer/Complaints regulations If you believe that digital publication of certain material infringes any of your rights or (privacy) interests, please let the Library know, stating your reasons. In case of a legitimate complaint, the Library will make the material inaccessible and/or remove it from the website. Please Ask the Library: https://uba.uva.nl/en/contact, or a letter to: Library of the University of Amsterdam, Secretariat, Singel 425, 1012 WP Amsterdam, The Netherlands. You will be contacted as soon as possible. UvA-DARE is a service provided by the library of the University of Amsterdam (https://dare.uva.nl) Download date:26 Nov 2021 Towards Reconfiguration and Self-Adaptivity in S-Net — Draft — Frank Penczek1 , Sven-Bodo Scholz1 and Clemens Grelck1,2 1 University of Hertfordshire Department of Computer Science Hatfield, Herts, AL10 9AB, United Kingdom {f.penczek,s.scholz,c.grelck}@herts.ac.uk 2 University of Amsterdam Institute of Informatics Kruislaan 403, 1098 SJ Amsterdam, Netherlands [email protected] Abstract. Stream processing is a well-suited model for parallel programming, as it allows the programmer to design parallel algorithms intuitively by arranging computational tasks into a data-flow graph and consecutively constructing a streaming network from it. However, a network that was designed with a specific workload in mind will not work optimally if anticipated parameters, as for example data rates or computational costs per data item, change over time. To nonetheless achieve optimal performance, a restructuring of the network and re-implementation of computational components is inevitable. As the deployment of a revised network usually causes service disruption, we present a system that supports reconfiguration of streaming networks at runtime. The reconfiguration of networks can either be triggered externally, i.e. initiated by the user, or from within the network itself (self-adaptation) by, for example, monitoring certain runtime parameters. Our system is based on S-Net, a coordination language for asynchronous stream processing systems. S-Net supports the simultaneous use of computational components implemented in a range of programming languages and it offers network combinators to construct streaming networks from these components. We will introduce S-Net and extensions of the language that allow for reconfiguration and self-adaptation of networks at runtime. The extensions are designed as network combinators and integrate seamlessly into the existing language. 1 Introduction Parallel programming, which has traditionally been used for high-performance computing on large-scale parallel architectures, is going mainstream. The broad availability of inexpensive multi-core CPUs drives the demand for general purpose programming languages that enable programmers to harness the full computational power of these novel architectures. For languages as C, C++, Java, Fortran etc. several APIs are available that extend these languages by facilities for parallel programming. The APIs allow programmers to use their language of choice and to re-use legacy code but are rather low-level: MPI and PVM require explicit communication management via send- and receive calls. APIs as PThreads, which implement communication via shared memory, require explicit synchronisation and locking to ensure correct and deadlock-free execution. These APIs also require manual assignment of work to available processes or threads. OpenMP offers an higher-level approach through directives, but requires special compiler support. All these approaches intertwine management code and computational code which makes programming an error-prone process and obfuscates the resulting code. On the other end of the spectrum, there are languages with (partially) implicit parallelism. This high-level approach, which is taken by for example languages as SAC or Data Parallel Haskell, takes away the burden of implementing low-level and often quite complex tasks of work distribution, communication and synchronisation. Being able to entirely focus on the design of an algorithm, turns programming into a much more efficient process and leads to better readable and maintainable code. The only drawback is that programmers need to learn how to use these languages; legacy code cannot be reused and needs to be reimplemented. To combine the advantages of the above approaches but not their disadvantages, we propose a coordination language that strictly separates code for computation from code for coordination of computation. The model we have developed distinguishes between computational components that interact with each other and the design of a communication network over which the interaction is carries out. The computational aspect is kept as a separate concern – in fact, we allow arbitrary languages for the implementation of the computational components. The focus of the proposed language lies on the coordination aspect. It provides combinators to construct a streaming network which contains computational components as nodes. This approach especially supports reuse of legacy code without cluttering it up with code for the traditional APIs, as all communication is defined outside the computational components. It also allows for a very lean language design, as computational aspects are left to a programming language of the user’s choice. As indicated above, our system is in fact a coordination language for stream processing networks. Stream processing is a well-suited model for parallel programming, as it allows the programmer to design parallel algorithms intuitively by arranging computational tasks into a data-flow graph and consecutively constructing a streaming network from it. The amount of exposed concurrency is influenced by the design decisions made for decomposition of the problem into separate computational components, as each component may potentially be assigned to different computing resources. The topology of the network, which is constructed with the provided combinators, defines the communication scheme of the program. This allows development of parallel programs on a high level of abstraction and in an intuitive way: The program design is representable as an box-and-arrow diagram which hides the low-level and often complex requirements of communication and synchronisation issues. Ideally, any streaming network is designed with a target system in mind. The granularity of the decomposition is chosen to match the computing resources of the target system to generate an optimal workload. This, of course, requires knowledge about the target. If this knowledge is not available, a programmer can only design a very generic model. However, a network that was designed with a specific workload in mind will not work optimally if anticipated parameters, as for example data rates or computational costs per data item, change over time. To nonetheless achieve optimal performance, a restructuring of the network and re-implementation of computational components is inevitable. Once this reengineering has taken place, the generic model is superseded by a more specialised implementation which then is deployed. As the deployment of a revised network usually causes service disruption, our system supports reconfiguration of streaming networks at runtime. The reconfiguration of networks can either be triggered externally, i.e. initiated by the user, or from within the network itself (self-adaptation) by, for example, monitoring certain runtime parameters. Our approach to provide these facilities is twofold. Firstly, we promote networks to first class citizens of the language. That is, data items that are sent across the network may be networks itself. Secondly, we introduce a replacement combinator. This combinator marks (sub-)networks as replaceable by new versions of networks which it receives over the stream. The combinator ensures that replacement of networks is only carried out if a received network is compatible, i.e. we guarantee that the replacement process will not break the specified semantics of the overall system. This approach enables a user to react to changes of the environment, e.g. increase or decrease of resources, bandwidth changes, etc., and reconfigure the system accordingly by sending revised versions of sub-networks over the existing network infrastructure. As networks are first class citizens, revised versions of networks may also be created and emitted from withing networks itself. Combining this with a feedback combinator, our design is powerful enough to implement self-adaptive networks that dynamically reconfigure themselves based on runtime measurements of, for example, throughput or execution times. 2 Introducing S-Net to be included in the final version of this paper 3 Introducing S-NetΩ to be included in the final version of this paper 4 S-Net Language Components and Semantics Throughout the following chapters we shall use the following notation: A single italic letter, as for example p, denotes a single record. A single letter with an arrow on top denotes a stream of records, e.g. ~p. The concatenation of two streams is denoted by p~ ++ ~q (appending ~q to ~p), concatenation of an element and a stream by p ⊳ p~ (prefixing ~q by p) and ~q ⊲ p (appending p to ~q). An n-fold concatenation, denoted by ++ni=1 (~ pi ), expands to ~p1 ++ p~2 ++ ... ++ p~n . 4.1 Boxes and Primitive Boxes Boxes are the only components in S-Net that are able to process and modify data of record fields. On input of a single record, a box may produce an arbitrary number (including zero) of result records. A distinctive feature of S-Net is the fact that function f of rule Box may be implemented in an arbitrary programming language. f (p) = ~q Box : (p, boxf ) → (boxf, ~q) A synchro cell, the only stateful component in S-Net, is a facility to store and merge records that match a user-defined pattern. For this, synchro cells are parametrised over two patterns. Any inbound record is matched against these patterns. If a record matches a previously unmatched pattern, it is stored by the synchro cell, the pattern is marked as matched and no output is produced (rule Syncs ). An index at the lower-right corner of the synchro cell indicates this. If a pattern was matched before, the record is simply output again, as described by the Syncn rule. A record that matches the last remaining unmatched pattern triggers a merge of stored and inbound record. After merging and outputting the resulting record, the synchro cell will act as an identity component ( Syncm rule). If a record immediately matches both patterns, the record passes unmodified and the synchro cell again will act as an identity component, as shown by the Synci rule. Syncs ismatch(σa , pa ) ∧ ¬ismatch(σb , pa ) : (pa , Jσa , σb K) → (Jσa , σb Kpa , ǫ) Syncn ismatch(σa , p) ∧ ¬ismatch(σb , p) : (p, Jσa , σb Kpa ) → (Jσa , σb Kpa , p) Synci : ismatch(σa , p) ∧ ismatch(σb , p) (p, Jσa , σb K) → (id, p) ismatch(σb , p) Syncm : (p, Jσa , σb Kpa ) → (id, merge(pa , p)) The filter (see rule Filter ) is a versatile instrument to modify the structure of records. Filters can split records, rename, copy or discard fields and tags and even insert new tags and modify their value. The behaviour of each filter is controlled by a pattern σ and by a user-defined list α of aforementioned actions. The pattern defines which constituents of inbound records are accessible by the filter actions. Only fields and tags that are present in the pattern may be used in the action list. On arrival of a record, the actions are applied to the inbound record and all resulting records are output. The S-NetΩ filter is also equipped with pattern matching facilities for network functions. With this, it is possible to assign identifiers to sub-expressions of a function on the left-hand side of the filter and use these identifiers on the right-hand side to construct new network functions. The filter also features runtime variables that contain values of the current system clock tick and the average throughput seen by the filter. These values may be assigned to tags for later use. ~q = apply(α, p) Filter : (p, [σ -> α]) → ([σ -> α], ~q) 4.2 S-Net Combinators The four S-Net combinators, which are used to construct networks from boxes, primitive boxes and networks, are very briefly introduced here. The serial combinator connects the output of its left operand to the input of its right operand. The output of the right operand thereby forms the output of the newly constructed network. (~ p, M ) → (M ′ , p~′ ) (p~′ , N ) → (N ′ , ~q) (~ p, M..N ) → (M ′ ..N ′ , ~q) Ser : The choice combinator creates a new network by connecting its two operands in parallel. Records are routed to either of the operands depending on which operand is a more specific match. The specificity of the match is determined by analysing the type of the inbound record and the input type of the operands. If both operands match equally well, one is chosen non-deterministically. The choice combinator comes in two variants, deterministic and non-deterministic. The deterministic variant preserves the order of inbound and resulting outbound records. If record order is not a concern, the non-deterministic variant may be used. The Dchoice rule formalises the behaviour of the deterministic choice combinator. ∀ni=1 Dchoice : p, τM , τN ) (p~li , p~ri )i∈{1,..,n} = lrpsplit(~ ′ ′ ) : (p~li , Mi ) → (q~li , Mi+1 ) ∧ (p~ri , Ni ) → (q~ri , Ni+1 (~ p, M1 ||N1 ) → (Mn+1 ||Nn+1 , ++ni=1 (q~li ++ q~ri )) The inbound stream ~ p is divided into pairs of sub-streams (p~li , p~ri ) such that each (potentially empty stream) p~li (resp. p~ri )) contains records matching the input type of the left (resp. right) operand network. These pairs are processed by the operand networks, whose internal state may change due to synchro cells, and produce streams q~li and q~ri as result. The output streams are concatenated to a result stream and represent the result for one input pair. The overall outbound stream is constructed by concatenating result streams of all input pairs. The behaviour of the non-deterministic choice combinator is expressed by the NDchoice rule. p~l , p~r = lrsplit(~ p, τM , τN ) (~ pl , M ) → (M ′ , q~l ) (p~r , N ) → (N ′ , q~r ) NDchoice : (~ p, M |N ) → (M ′ |N ′ , ndzip(~ ql , q~r )) Any inbound stream of records p~ is divided into two separate sub-streams p~l and p~r , such that each record in p~l (resp. p~r ) matches the inbound type of the left (resp. right) operand of the choice combinator. The operand networks, whose internal state may change due to synchro cells, produce q~l and q~r as results. These result streams are non-deterministically merged, i.e. both streams may be arbitrarily interleaved. The star combinator requires an operand and a pattern for operation. Any inbound record that matches the pattern is immediately output. If the record does not match the pattern, it is sent to the operand. At the output of the operand, the same process repeats. If the result matches the patten, it is output, otherwise a new instance of the operand is spawned and the record is sent to it. The star combinator is available as deterministic and non-deterministic combinator. The deterministic variant guarantees that any result of an earlier input will exit the network before any other result of a later input, i.e. outbound streams of multiple inbound records are not interleaved and in the same order of their corresponding inbound records. Dstar (~ p, (M..M ∗{σ})||[σ -> τσ ]) → (M ′ , ~q) (~ p, M ∗∗{σ}) → (M ′ , ~q) : (~ p, (M..M ∗{σ})|[σ -> τσ ]) → (M ′ , ~q) NDstar : (~ p, M ∗{σ}) → (M ′ , ~q) The split combinator routes inbound records to different instances of its operand depending on the value of a specified tag. The name κ of the tag that determines the instance of the operand is given as parameter to the split combinator. Each instance of the operand stays associated with the combinator and is reused whenever a record is processed that holds the appropriate instance value. [todo: The Dsplit is too restrictive and has to be defined on streams to refelct the fact that records of different branches can be processed concurrently. Add subscript or different font for N to annotate associated set of instances.] value(κ, p) = j Dsplit : (p, Nj ) → (Nj′ , ~q) (p, N !!κ) → (N !!κ, ~q) ∀ni=1 pi ∈ ~p : value(κ, pi ) = vi NDsplit : 4.3 (pi , Nvi ) → (Nv′ i , ~qi ) (~ p, N !κ) → (N !κ, ndzip(~q1 , ..., ~qn )) Id, Empty and Map Rule The following rules are merely ’helper-rules’. The Id rule allows records to be passed on without any alteration. An empty stream has no effect on any component, as shown by the Empty rule. The Map rule allows to derive a semantics for streams if component rules are defined on single records. Id : (p, id) → (id, p) Empty : (ǫ, M ) → (M, ǫ) ∀ni=1 : (pi , Mi ) → (Mi+1 , q~i ) ~s = ++ni=1 (~ qi ) Map 4.4 : (~ p, M1 ) → (Mn+1 , ~s) Algorithms eval eval :: pattern → record → Bool eval σ p = ... ismatch ismatch :: pattern → record → Bool ismatch σ p = p 4 σ ∧ eval σ r score score :: pattern → record → N0 ∪ {−1} score σ p = ... bestmatch bestmatch :: record → pattern → pattern → set of pattern bestmatch r σl σr = {σi | i, j ∈ {l, r} ∧ score σi r ≥ score σj r} prefix prefix :: stream → pattern → pattern → (stream, stream) prefix p~ σl σr = case ~ p of ǫ → (ǫ,ǫ) p : ps ~ | ndsel (bestmatch p σl σr ) == σl → (p:~q, ~r) p : ps ~ | otherwise → (ǫ, p~) where (~ q , ~r) = prefix ps ~ σl σr splitOnePair splitOnePair :: stream → pattern → pattern → (stream, stream, stream) splitOnePair p~ σl σr = case ~ p of ǫ → (ǫ, ǫ, ǫ) p : ps ~ → (~ ql , q~r , ~r) where (~ ql , ~t) = prefix p~ σl (q~r , ~r) = prefix ~t σr lrpsplit lrpsplit :: stream → pattern → pattern → (stream of streams, stream of streams) lrpsplit ~ p σl σr = case ~ p of ǫ → (~ǫ,~ǫ) ~ p : ps ~ → (l~p : l~pl , r~p : r~~pl ) where (l~p , r~p , ~ q ) = splitOnePair p~ σl σr ~ ~ ~ (lpl , r~pl ) = lrpsplit ~q σl σr lrsplit lrsplit :: stream → pattern → pattern → (stream, stream) lrsplit ~ p σl σr = let (p~ ~l , p~ ~r ) = lrpsplit ~ p σl σr in (flatten p~ ~l , flatten p~ ~r ) merge merge :: record → record → record record p~ ~q = p~ ∪ ((~ q \ BT (~ q )) \ (~ p ∩ q~)) apply apply :: record → action → stream apply p α = ... 5 Components and Semantics of the Extended Language We extend the S-Net core language by two combinators which will be powerful enough to allow for reconfiguration as well as self-adaptation scenarios. As S-NetΩ is an extension to S-Net, it includes all combinators of the original language. In this paper, all components that are shared between S-Net and S-NetΩ will be referred to as S-Net components, whereas components that are not part of core language will be referred to as S-NetΩ components. 5.1 Special Records and Tags to be included in the final version of the paper 5.2 Network Combinators The ρ-combinator replaces its current network function if an inbound record contains a compatible replacement function. A network function is considered compatible if it is a subtype of the current function. Any record that does not carry a suitable replacement function is processed by the current network function. ∃Fp ∋ f 4 M (p, f ) → (X, ~q)∨ ∀Fp ∋ f 64 M (p, M ) → (X, ~q) Rho : (p, ρ[M ]) → (ρ(X), ~q) The µ-combinator constitutes a feedback combinator. Similar to the star combinator, the behaviour of this combinator is influenced by a user-defined pattern. The pattern is matched against inbound records at the output of the network the combinator is applied to. Records that do not match the specified pattern are output. In this case, the combinator has no observable effect. All records that match the pattern are re-inserted to the operand network. As the Mu shows, the feedback path of the combinator has priority over the inbound stream. Records are only read from the inbound stream when all records of the feedback path have been processed. A non-deterministic variant of this combinator, which relaxes this strict behaviour and allows for interleaved feedback and inbound record streams, is currently under investigation and remains as future work. (p, M ) → (M ′ , q~′ ) ~l, ~r = lrpsplit(q~′ , σ, {}) (~l, M ′ µ{σ}) → (M ′′ µ{σ}, ~q) Mu : 6 (p, M µ{σ}) → (M ′′ µ{σ}, ~q ++ q~′ ) Example: Reconfiguration and Adaptation Based on Throughput Monitoring to be included in the final version of the paper 7 Related Work to be included in the final version of the paper 8 Conclusion and Future Work We have presented a coordination language for stream processing that natively supports reconfiguration and restructuring of the network topology and its components. This was achieved by promoting networks to first class citizens of the language. Due to this design, networks may not only be sent across the streaming network, they may also be emitted by components from within networks itself. This further extended our system by adaptation abilities, which render it possible to implement self-modifying networks. The self-adaptation process can be triggered by various sources, as for example an increase or decrease of available computing resources and fluctuating execution times of computational components for inbound data. Rather than providing reconfiguration and adaptivity facilities implicitly and hiding it from the user, e.g. by implementing these as opaque mechanisms of a runtime system, we designed these as a native part of the language. By extending the core S-Net language by only two combinators, we empower users to explicitly implement reconfiguration and self-adaptation scenarios. A distinct feature of our approach is the possibility to replace networks by new versions without having to specify alternative implementations at deploy or even design time of the original network. Although our approach enters the domain of self-modifying code, the system guarantees static properties: For any data item that enters the network, it is guaranteed that a path exists for it through the entire network. Replacement of networks is only carried out if a newly received network is of compatible type and thus does not break the specified semantics. The main enabling factor for this is the strict separation of computational languages and the coordination language as this allows for a very concise type system. What we have presented in this paper is work in progress. A non-deterministic variant of the replacement and feedback operators are under development. The record-discarding behaviour of synchro-cells at replacement events is not fully satisfactory and may need refinement. Extended semantics for this and a formal definition of the type system for S-NetΩ remain as future work.