void GenerateRoutingTree()
{
	Uint16 i;
	Uint16 nodesToPartition[MAX_NUM_NODES], shortestDistances[MAX_NUM_NODES + 1][MAX_NUM_NODES + 1];

	// Calculate the node and edge list
	GenerateNodeList(nodesToPartition);
	GenerateEdgeList();

	// Calculate the shortest paths for all nodes to all nodes
	CalculateLongestMinPaths(shortestDistances,nodesToPartition);

	// Generate the root node in the partition tree
	globals.routing.partitionTree[0].nodeInformation.leftChildNode = TREE_NODE_UNDEFINED;
	globals.routing.partitionTree[0].nodeInformation.rightChildNode = TREE_NODE_UNDEFINED;
	globals.routing.partitionTree[0].nodeInformation.parentNode = TREE_NODE_UNDEFINED;
	globals.routing.partitionTree[0].nodeInformation.treeLevel = 0;
	globals.routing.partitionTree[0].nodeInformation.numGraphNodesInTreeNode = globals.routing.graphInfo.numNodes;
	for(i = 0; i < globals.routing.graphInfo.numNodes; i++)
		globals.routing.partitionTree[0].graphNodesInTreeNode[i] = nodesToPartition[i];
	for(i = 1; i < (MAX_NUM_NODES - 1) * 2 - 1; i++)
		globals.routing.partitionTree[i].nodeInformation.numGraphNodesInTreeNode = 0;

	// Partition the routing tree
	PartitionGraph(0,shortestDistances);

	// Calculate the weights of the nodes
	CalculatePartitionTreeWeights();
}
Ejemplo n.º 2
0
bool ManualAllocator::Allocate(GenericEngine * engine,GraphExecutor * graph_executor, Graph * graph, std::vector<Subgraph *>& sub_list)
{
    //step 1: assign dev_executor for all  nodes
    std::set<DevExecutor *> exec_set;

    int node_number=graph->seq_nodes.size();
    DevExecutor * dev_executor=nullptr;

    for(int i=0;i<node_number;i++)
    {
        Node * node=graph->seq_nodes[i];
        Operator * op=node->GetOp();

        if(op->GetName()=="Input" || op->GetName()=="Const")
            continue;

        if(node->ExistAttr("dev_id"))
        {
              const std::string& dev_id=any_cast<std::string>(node->GetAttr("dev_id"));

              if(DevExecutorManager::GetDevExecutorByID(dev_id,dev_executor))
              {
                   node->SetAttr("dev_executor",dev_executor);
                   exec_set.insert(dev_executor);
                   continue;
              }
	      else
	      {
	            LOG_ERROR()<<"cannot find dev exeuctor: "<<dev_id
                               <<" for node: "<<node->GetName()<<"\n";
                    return false;				
	      }
        }

        //not assigned using the default one
        //first: to check if the graph default one

        if(graph->ExistAttr("default_executor"))
        {
             const std::string& dev_id=any_cast<std::string>(graph->GetAttr("default_executor"));
        
             if(DevExecutorManager::GetDevExecutorByID(dev_id,dev_executor))
              {
                   node->SetAttr("dev_executor",dev_executor);
                   exec_set.insert(dev_executor);
                   continue;
              }
              else
              {
                    LOG_ERROR()<<"cannot find graph default dev exeuctor: "<<dev_id
                               <<" for node: "<<node->GetName()<<"\n";
                    return false;
              }     
                   
        }
       
        //get  the  system default one
        if(!DevExecutorManager::GetDefaultDevExecutor(dev_executor))
        {
                LOG_ERROR()<<"failed to assign dev executor for node: "<<node->GetName()<<"\n";
                return false;
        }
       

        node->SetAttr("dev_executor",dev_executor);
        exec_set.insert(dev_executor);
    }


    //step 2: partition graph into subgraph according to dev_executor allocation 

    if(exec_set.size()>1)
        PartitionGraph(engine,graph_executor,graph,sub_list);
    else
        SameGraph(graph,dev_executor,sub_list);

    return true;
}
void PartitionGraph(Uint16 currentPartitionTreeNode, Uint16 shortestDistances[][MAX_NUM_NODES + 1])
{
	Uint16 i, j, k, bestA, bestB, bestG, longestMinPath[2], longestPath = 0, numNodes, numIterations = 0, *A1, *B1;
	Int16 gMax, temp, gCheck, g[MAX_NUM_NODES - 1], Da[MAX_NUM_NODES - 1], Db[MAX_NUM_NODES - 1];

	numNodes = globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.numGraphNodesInTreeNode;
	if(numNodes == 2)
	{
		// Allocate and initialize the child nodes in the tree
		for(i = 0; i < (MAX_NUM_NODES - 1) * 2 - 1; i++)
		{
			if(globals.routing.partitionTree[i].nodeInformation.numGraphNodesInTreeNode == 0)
			{
				globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode = i;
				globals.routing.partitionTree[i].nodeInformation.parentNode = currentPartitionTreeNode;
				globals.routing.partitionTree[i].nodeInformation.leftChildNode = TREE_NODE_UNDEFINED;
				globals.routing.partitionTree[i].nodeInformation.rightChildNode = TREE_NODE_UNDEFINED;
				globals.routing.partitionTree[i].nodeInformation.numGraphNodesInTreeNode = 1;
				globals.routing.partitionTree[i].nodeInformation.treeLevel = globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.treeLevel + 1;
				if(globals.routing.partitionTree[i].nodeInformation.treeLevel + 1 > globals.routing.graphInfo.treeHeight)
					globals.routing.graphInfo.treeHeight = globals.routing.partitionTree[i].nodeInformation.treeLevel + 1;
				globals.routing.partitionTree[i].graphNodesInTreeNode[0] = globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[0];
				break;
			}
		}
		for(i = globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode + 1; i < (MAX_NUM_NODES - 1) * 2 - 1; i++)
		{
			if(globals.routing.partitionTree[i].nodeInformation.numGraphNodesInTreeNode == 0)
			{
				globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode = i;
				globals.routing.partitionTree[i].nodeInformation.parentNode = currentPartitionTreeNode;
				globals.routing.partitionTree[i].nodeInformation.leftChildNode = TREE_NODE_UNDEFINED;
				globals.routing.partitionTree[i].nodeInformation.rightChildNode = TREE_NODE_UNDEFINED;
				globals.routing.partitionTree[i].nodeInformation.numGraphNodesInTreeNode = 1;
				globals.routing.partitionTree[i].nodeInformation.treeLevel = globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.treeLevel + 1;
				if(globals.routing.partitionTree[i].nodeInformation.treeLevel + 1 > globals.routing.graphInfo.treeHeight)
					globals.routing.graphInfo.treeHeight = globals.routing.partitionTree[i].nodeInformation.treeLevel + 1;
				globals.routing.partitionTree[i].graphNodesInTreeNode[0] = globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[1];
				break;
			}
		}
	}
	else
	{
		// Find the longest path using the given nodes
		longestMinPath[0] = 0;
		longestMinPath[1] = 0;
		for(i = 0; i < numNodes; i++)
		{
			for(j = 0; j < numNodes; j++)
			{
				if(shortestDistances[globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i]][globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[j]] > longestPath)
				{
					longestPath = shortestDistances[globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i]][globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[j]];
					longestMinPath[0] = globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i];
					longestMinPath[1] = globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[j];
				}
			}
		}

		// Sort the nodes to partition by distance from longestMinPath[0]
		for(i = 0; i < numNodes - 1; i++)
		{
			for(j = i + 1; j < numNodes; j++)
			{
				if(shortestDistances[longestMinPath[0]][globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[j]] < 
					shortestDistances[longestMinPath[0]][globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i]])
				{
					temp = globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i];
					globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i] = globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[j];
					globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[j] = temp;
				}
			}
		}

		// Allocate and initialize the child nodes in the tree
		for(i = 0; i < (MAX_NUM_NODES - 1) * 2 - 1; i++)
		{
			if(globals.routing.partitionTree[i].nodeInformation.numGraphNodesInTreeNode == 0)
			{
				globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode = i;
				globals.routing.partitionTree[i].nodeInformation.parentNode = currentPartitionTreeNode;
				globals.routing.partitionTree[i].nodeInformation.treeLevel = globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.treeLevel + 1;
				if(globals.routing.partitionTree[i].nodeInformation.treeLevel + 1 > globals.routing.graphInfo.treeHeight)
					globals.routing.graphInfo.treeHeight = globals.routing.partitionTree[i].nodeInformation.treeLevel + 1;
				break;
			}
		}
		for(i = globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode + 1; i < (MAX_NUM_NODES - 1) * 2 - 1; i++)
		{
			if(globals.routing.partitionTree[i].nodeInformation.numGraphNodesInTreeNode == 0)
			{
				globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode = i;
				globals.routing.partitionTree[i].nodeInformation.parentNode = currentPartitionTreeNode;
				globals.routing.partitionTree[i].nodeInformation.treeLevel = globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.treeLevel + 1;
				if(globals.routing.partitionTree[i].nodeInformation.treeLevel + 1 > globals.routing.graphInfo.treeHeight)
					globals.routing.graphInfo.treeHeight = globals.routing.partitionTree[i].nodeInformation.treeLevel + 1;
				break;
			}
		}

		// Partition the tree
		globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode].nodeInformation.numGraphNodesInTreeNode = numNodes / 2;
		for(i = 0; i < numNodes / 2; i++)
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode].graphNodesInTreeNode[i] = 
				globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i];
		for(i = numNodes / 2; i < MAX_NUM_NODES - 1; i++)
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode].graphNodesInTreeNode[i] = 0;

		globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode].nodeInformation.numGraphNodesInTreeNode = numNodes - (numNodes / 2);
		for(i = numNodes / 2; i < numNodes; i++)
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode].graphNodesInTreeNode[i - (numNodes / 2)] = 
				globals.routing.partitionTree[currentPartitionTreeNode].graphNodesInTreeNode[i];
		for(i = numNodes; i < MAX_NUM_NODES + (numNodes / 2); i++)
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode].graphNodesInTreeNode[i - (numNodes / 2)] = 0;
		
		// Minimize the cut point using a slightly modified version Kernighan-Lin's algorithm (basically I added support for an odd number of graph nodes)
		A1 = globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode].graphNodesInTreeNode;
		B1 = globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode].graphNodesInTreeNode;
		
		do
		{
			CalculateDvalues(Da,Db,A1,B1);

			for(i = 0; i < numNodes; i++)
			{
				//find a[x] from A1 and b[y] from B1, such that g[j] = D[a[x]] + D[b[y]] - 2*connection(a[x],b[y]) is maximal. A1 and B1 are sorted to align with the sorted g
				g[i] = SHRT_MIN;
				for (j = i; j < numNodes; j++)
				{
					for(k = i; k < numNodes; k++)
					{
						if(A1[j] != 0 && B1[k] != 0)
						{
							switch(A1[j])
							{
								case 1: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node1; break;
								case 2: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node2; break;
								case 3: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node3; break;
								case 4: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node4; break;
								case 5: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node5; break;
								case 6: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node6; break;
								case 7: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node7; break;
								case 8: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node8; break;
								case 9: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node9; break;
								case 10: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node10; break;
								case 11: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node11; break;
								case 12: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node12; break;
								case 13: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node13; break;
								case 14: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node14; break;
								case 15: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node15; break;
								case 16: gCheck = Da[j] + Db[k] - 2 * globals.routing.graphInfo.adjacencyMatrix[B1[k]].node16; break;
							}
							if(gCheck > g[i])
							{
								bestA = j;
								bestB = k;
								g[i] = gCheck;
							}
						}
					}
				}
				
				if(g[i] != SHRT_MIN)
				{
					//move A1[j] to B1[k] and B1[k] to A1[j]
					temp = A1[bestA];
					A1[bestA] = B1[bestB];
					B1[bestB] = temp;

					// Reorder A1 and B1 so that g[i] aligns with A1[i] and B1[i]. This is how nodes are marked as having been reordered (everything left of i has been marked).
					temp = A1[bestA];
					A1[bestA] = A1[i];
					A1[i] = temp;
					temp = B1[bestB];
					B1[bestB] = B1[i];
					B1[i] = temp;
				}

				// Update the D values
				CalculateDvalues(Da,Db,A1,B1);
			}

			//find k which maximizes gMax, the sum of g[1],...,g[k]
			gMax = SHRT_MIN;
			for(j = 0; j < numNodes; j++)
			{
				gCheck = 0;
				for(k = 0; k <= j; k++)
				{
					if(g[k] != SHRT_MIN)
						gCheck += g[k];
				}
				if(gCheck > gMax)
				{
					gMax = gCheck;
					bestG = j;
				}
			}
			if (gMax > 0)
			{
				// Undo the the previous swap for all indeces after k
				for(j = bestG + 1; j < numNodes; j++)
				{
					if(A1[j] != 0 && B1[j] != 0)
					{
						temp = A1[j];
						A1[j] = B1[j];
						B1[j] = temp;
					}
				}
			}
			else
			{
				// Undo all swaps
				for(j = 0; j < numNodes; j++)
				{
					if(A1[j] != 0 && B1[j] != 0)
					{
						temp = A1[j];
						A1[j] = B1[j];
						B1[j] = temp;
					}
				}
			}

			numIterations++;

		} while(gMax > 0 && numIterations < MAX_GRAPH_PARTITION_ITERATIONS);

		// Partition the sub-groups if there are more than two nodes left, otherwise finalize this branch
		if(globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode].nodeInformation.numGraphNodesInTreeNode > 1)
			PartitionGraph(globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode,shortestDistances);
		else
		{
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode].nodeInformation.leftChildNode = TREE_NODE_UNDEFINED;
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.leftChildNode].nodeInformation.rightChildNode = TREE_NODE_UNDEFINED;
		}
		if(globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode].nodeInformation.numGraphNodesInTreeNode > 1)
			PartitionGraph(globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode,shortestDistances);
		else
		{
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode].nodeInformation.leftChildNode = TREE_NODE_UNDEFINED;
			globals.routing.partitionTree[globals.routing.partitionTree[currentPartitionTreeNode].nodeInformation.rightChildNode].nodeInformation.rightChildNode = TREE_NODE_UNDEFINED;
		}
	}
}