PerOpteryx/Taskmodel

Aus SDQ-Wiki

Taskmodel description

The taskmodel is the interface between the Palladio Component Model (PCM) and the performance model needed for the analytical optimisation. Additionally, the cost model and the design decision model are required for the full optimisation problem specification. The metamodel of taskmodel makes use of the PCM metamodel.

Rationale

The taskmodel is a simplified performance model that serves as an intermediate model for transformations from PCM models to the input for Danilo's optimisation models. It targets to include the aspects of the PCM model that are relevant for Danilo's optimisation. Those aspects include:

  • A notion of a Task. A task is a single action that has a certain resource demand and a probability of failure. It corresponds to an InternalAction in the PCM.
  • The control flow from a Task to another Task. These are modelled by Edges. Branches are modelled by branchProbabilities for Edges.
  • The allocation of a Task to a server

From this description, Danilo's performance model and reliability model can be built. Many other aspects of the PCM are abstracted away, such as component boundaries, passive resources, parametrisation, ...

For the optimisation, we need a whole set of possible models. Possible changes of the initial models are described as Degrees of Freedom in the PCM. From the .designdecision model, the available degrees of freedom can be derived. Allocation and hardware changes are uncritical, as they do not affect the taskmodel. Only component replacement changes are more difficult to incorporate, because they lead to different Tasks being executed. As one component can contain several Tasks, the information which Tasks have to be replace to form a certain alternative solution is not directly available. For this reason, we introduced the notion of an Alternative in the taskmodel. Each Alternative constrains a number of AlternativeTasks. If an Alternative is selected, all contained AlternativeTasks replace their original Task (referenced by the "Task_alternativeTask" association). This ways of specifying alternatives is the initial idea and might be refined to something more handy.

TODO: Missing elements in the taskmodel are the workload and the number of users.

The metamodel is described in html documentation:

Installation

To work with the taskmodel model, it is easiest to use Eclipse with the PCM installed. Additionally, you need the three metamodel' sources.

Download

Import the sources to your Eclipse

  • Import all projects you can find in these two directories in your Eclipse workspace (should be 10 proojects)
  • Compile the projects (should be done automatically)

Check the Example model

  • Start a new Eclipse instance with the 10 new plugins compiled from the projects. This is quite easy in Eclipse
    • Go to Run -> Run Configurations ...
    • Double-click "Eclipse Application" on the left to create a new run configuration. If you like, rename the configuration and adjust other settings, such as the workspace to use.
    • Click "Run"
    • A second Eclipse instance is started that includes our projects as plugins.
  • In the newly started Eclipse, import the PCM2TaskmodelExample project

Explanation of Example

The example system is very easy with just two components. Go through the following sections step by step to get an overview.

Repository

Open default.respository_diagram to see the repository with the available components. You see that our Repositoty contains two components: "Component1" and "AlternativeComponent". Both provide the same Interface "Interface1". Interface1 defines that there should be a Service called "service1". Thus, in the two component, you find one behaviour description each for service1 called "SEFF service1". Double-click the SEFF to open the behaviour description. Both components do two actions when called, "action1" and "action2". The resource demand (i.e. the time demanded from the CPU) is shown inside each action. For example, action1 of Component1 has a resource demand of 2. To see the failure probability of this action, rightclick on the action and select "Show properties view". In the opening tab Properties you find the Failure Probability.

Taskmodel screenshot-repository.png

System

The system model is not so relevant for us, so there will only be a brief explanation. Open default.system_diagram to see the architecture of our system. In this case, it is very easy. The system only contains a single component. The component is put into the system using a so-called AssemblyContext. Click on the AssemblyContext to see which component is assembled in the system in the Properties view. As default, Component1 is put into the system.

Allocation

Open default-allocation_diagram to see the allocation of the component and the available servers. You see that two servers are available, "server1" and "server2". Currently, the component is allocated to server1. In this view, you do not see any details about the servers. Open the resource environment for that (see next section).

Taskmodel screenshot-allocation.png

Resource Environement

Open My.resourceenvironment to see the configuration of the servers. Open first element to see the servers and their CPU specification as shown in the picture.

Taskmodel screenshot-resourceenvironment.png

Usage model

The system workload is defined in the usage model. Open default.usagemodel_diagram. You find the OpenWorkloadSpecification. It says that the interarrival time of users is exponentially distributed with a rate of 0.5. This means one user arrives every 2 time units (lets assume seconds) in average. This means the average arrival rate is 0.5.

Cost model

Open My.cost to see the costs of the system. For each of the two components, a cost is specified. In the image below, you see the cost for Component1 in the Property tab. The initial cost of this component is 2. I did not specify any operating cost here.

Also servers can have cost. Here, we assigned the cost to their CPU as FixedProcessingResourceCost. Server1's CPU has a cost of 1. The faster CPU of server2 has a cost of 2.

Taskmodel screenshot-cost.png

Degrees of Freedom

Open example.designdecision to see the definition of the optimisation problem. We have defined four degrees of freedom. The first two degrees AllocationDegree and AssembledComponentDegree are the relevant ones for us. I added the ProcessRateDegree to show what else is possible in my approach.

Each degree references a model element as Changeable Entity. For example, the AllocationDegree references the AllocationContext of the one component in the System. This allows to independently change the component implementation inside the AllocationContext's AssemblyContext without affecting thgus degree of freedom, that only talks about the AllocationContext. Additionally, the degrees of freedom define the possible values for this entities. For example, the AllocationContext "Allocation _UfL2QKOXEd6D1ZKDqAnLPA" can be deployed to server1 or server2. Click on the Domain of Entites entry in the Properties tab, then click on the small button appearing on the right of the line to edit the possible values.

For the ProcessingRateDegrees, the possible values are defined as an interval "from" to "to". Additionally, you can specify whether the endpoints of the intervals are included or not. The ProcessingRateDegree references a server (ResourceContainer) and additional a ProcessingResourceSpecification to decide which of the server's resource is meant (here: the CPU resource).

Taskmodel screenshot-designdecisions.png

Input model: Taskmodel model

Now the most interesting model: The taskmodel of the architecture described above!

The Tasklist element contains the tasks of the initial system. In our case, we have two tasks, one for each action in component1. An Edge connects the two tasks.

Additionally, the taskmodel defines the alternative tasks. Here, one Alternative is to use alternativeComponent instead of component1. So, the alternative contains the two tasks for the actions of alternativeComponent. Each AlternativeTask references its original task to allow replacing it. Thus, you can derive the different paths if different components are replaced.

Taskmodel screenshot-taskmodel.png

Output model: Candidates

There is a model to define candidate solutions based on the design decision model described above. The main element is a Choice: It defines which of the options of a degree of freedom have been chosen. A Candidate is a set of choices, one for each degree of freedom in our model. Finally, the Candidates element contains a number of Candidate.

The metamodel of this model is shown below.

Taskmodel screenshot-decision and choice.png

Taskmodel screenshot-choices.png

An example instance for the running example used on this wiki page is shown below. This is a candidate with four choices, one for each degree of freedom described above.

Taskmodel screenshot-choice instance.png

Here is some example code to create a simpler Candidates element with one candidate solution that has two choices (one EnumerationChoice for choosing an alternative component, and one ContinuousRangeChoice for choosing a processing rate). The required input are the degree of freedom that defines the processing rate change (procRateDegree), the degree of freedom that defines the alternative component degree (assembledComponentDegree) and the chosen PCM component (chosenComponent).

Note that this code is not necessarily exactly what you will need, it is just to illustrate how to use the classes. The strange comments are for making the wiki show this more nicely.

 import de.uka.ipd.sdq.pcm.designdecision.Candidate;
 import de.uka.ipd.sdq.pcm.designdecision.Candidates;
 import de.uka.ipd.sdq.pcm.designdecision.ContinousRangeChoice;
 import de.uka.ipd.sdq.pcm.designdecision.DegreeOfFreedom;
 import de.uka.ipd.sdq.pcm.designdecision.EnumerationChoice;
 import de.uka.ipd.sdq.pcm.designdecision.designdecisionFactory;
 import de.uka.ipd.sdq.pcm.repository.RepositoryComponent;
 
 public Candidates createExampleInput(DegreeOfFreedom procRateDegree, RepositoryComponent chosenComponent, DegreeOfFreedom assembledComponentDegree) {
   Candidates candidates = designdecisionFactory.eINSTANCE.createCandidates();
   Candidate candidate1 = designdecisionFactory.eINSTANCE.createCandidate();
     
   // example choice with speed 10 for the server from the procRateDegree 
   ContinousRangeChoice procRateChoice = designdecisionFactory.eINSTANCE.createContinousRangeChoice();
   procRateChoice.setChosenValue(10);
   procRateChoice.setDegreeOfFreedom(procRateDegree);
         
   // example choice that chooses  chosenComponent for degree   assembledComponentDegree
   EnumerationChoice assembledComponentChoice = designdecisionFactory.eINSTANCE.createEnumerationChoice();
   assembledComponentChoice.setEntity(chosenComponent);
   assembledComponentChoice.setDegreeOfFreedom(assembledComponentDegree);
   		   
   candidate1.getChoice().add(procRateChoice);
   candidate1.getChoice().add(assembledComponentChoice);
   		   
   candidates.getCandidate().add(candidate1);
   	   
   return candidates;
 }

The problem here is that the model needs to be linked to the original PCM model. Thus, we probably also need to merge the input models, because only then, the link to the original PCM model elements will be retained. Otherwise, I cannot know which PCM model element was meant.

Integration with the Milano optimisation approach

It would be perfect if your developed program would be another Eclipse plugin (or a set thereof). It should provide a method that takes a taskmodel instance (i.e. a TaskList), a cost model instance (i.e. a CostRepository) and a design decision model instance (i.e. a Problem). As a return value, a Candidates model element with the different evaluated candidates would be perfect. Maybe we should also add some information on the evaluated performance and cost.

For testing purposes, you would need another launch plugin that reads in a model from the filesystem and passes it on to your plugins. If you need help with that, let me know.

Read in all models

You can read in the models described above as follows. You need the downloads described above for that, and you need to set up the build paths correctly (see PerOpteryx/Taskmodel#Installation above). Let me know if there are problems to access the code.

Then, you can use this method to read in models from the xml files (the .repository file, the .designdecision file etc.). Just copy the method below and use it (as shown in the next exaple below).

	/**
	 * Copied From de.uka.ipd.sdq.pcmsolver.models.PCMInstance.
	 * 
	 * @param fileName
	 *            the filename specifying the file to load from
	 * @return The EObject loaded from the file
	 */
	public static EObject loadFromXMIFile(final String fileName) {
		// Create a resource set to hold the resources.
		ResourceSet resourceSet = new ResourceSetImpl();

		// Register the appropriate resource factory to handle all file
		// extensions.
		resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
				.put(Resource.Factory.Registry.DEFAULT_EXTENSION,
						new XMIResourceFactoryImpl());

		// Register the package to ensure it is available during loading.
		registerPackages(resourceSet);

		// Construct the URI for the instance file.
		// The argument is treated as a file path only if it denotes an existing
		// file. Otherwise, it's directly treated as a URL.
		File file = new File(fileName);
		URI uri = file.isFile() ? URI.createFileURI(file.getAbsolutePath())
				: URI.createURI(fileName);

		Resource resource = null;
		// Demand load resource for this file.
		try {
			resource = resourceSet.getResource(uri, true);
		} catch (Exception e) {
			Logger.getLogger("de.uka.ipd.sdq.dsexplore").error(e.getMessage());
			return null;
		}

		EObject eObject = (EObject) resource.getContents().iterator().next();
		return EcoreUtil.getRootContainer(eObject);
	}

To work with the models, you need to load the designdecision file. It references the other and can automatically load them in the background. Here is some example code to read in the example.designdecision file and to print out some information about it.

 String filenameTaskmodel = "pathToMyProject/My.taskmodel";
 EObject eTaskmodel = EMFHelper.loadFromXMIFile(filenameTaskmodel);
 if (!(eproblem instanceof TaskList)){
	throw new RuntimeException("Cannot read task model file "+filename+". Please create a new one.", null));
 }
 TaskList taskList = (TaskList)eTaskmodel ;

 String filename = "pathToMyProject/example.designdecision";
 EObject eproblem = EMFHelper.loadFromXMIFile(filename);
 if (!(eproblem instanceof Problem)){
	throw new RuntimeException("Cannot read design decision file "+filename+". Please create a new one.", null));
 }
 Problem problem = (Problem)eproblem;

 List<DegreeOfFreedom> degrees = problem.getDesigndecision();
 for (DegreeOfFreedom degreeOfFreedom : degrees) {
 System.out.println("I am a degree of freedom of type "+degreeOfFreedom.getClass()+" and define how to change "+degreeOfFreedom.getChangeableEntity().getEntityName());
 if (degreeOfFreedom instanceof AllocationDegree){
	System.out.println("This is an allocation degree");
	AllocationDegree allocDegree = (AllocationDegree) degreeOfFreedom;
				
	//this is the component whose allocation is defined by this degree
	RepositoryComponent component = (RepositoryComponent) degreeOfFreedom.getChangeableEntity();

	// This contains the list of servers to which the component may be allocated 
	List<Entity> entityList = allocDegree.getDomainOfEntities();
	for (Entity entity : entityList) {
		// you need to cast the server to access it properly. A server is called ResourceContainer in the PCM. 
		ResourceContainer server = (ResourceContainer)entity;
	}
			
 } else if (degreeOfFreedom instanceof AssembledComponentDegree){
	System.out.println("This is an assembled component degree.");
	AssembledComponentDegree alternativeComponentdegree = (AssembledComponentDegree)degreeOfFreedom;
				
	//This is the place in the system / architcture where different alternative components can be placed in
	AssemblyContext placeInTheSystem = (AssemblyContext)alternativeComponentdegree.getChangeableEntity();
				
	//This contains the list of components that can be used here
	List<Entity> entityList = alternativeComponentdegree.getDomainOfEntities();
	for (Entity entity : entityList) {
		//again you need to cast
		RepositoryComponent alternativeComponent = (RepositoryComponent)entity;
	}
 } else if (degreeOfFreedom instanceof ContinuousProcessingRateDegree){
	System.out.println("This is an degree to change processor speed");
	ContinuousProcessingRateDegree procRateDegree = (ContinuousProcessingRateDegree)degreeOfFreedom;
				
	//This is the server that can be changed
	ResourceContainer server = (ResourceContainer)procRateDegree.getChangeableEntity();
	//this is the type of resource to change here (e.g. CPU). Lets assume for now there is always just CPU. 
	ProcessingResourceType resourceType = procRateDegree.getProcessingresourcetype();
				
	//This is the range of allowed values, with max and min
	double lowerBoundForProcessingRate = procRateDegree.getFrom();
	double upperBoundForProcessingRate = procRateDegree.getTo();
 }