Beispiel #1
0
        /// <summary>
        /// Saves this graph on a given binary stream.
        /// </summary>
        public virtual void Serialize(BuildXLWriter writer)
        {
            Contract.Requires(writer != null, "Argument writer cannot be null");
            uint max = (uint)m_lastNodeId;

            writer.Write(max);
            writer.Write(m_edgeCount);

            for (uint node = 1; node <= max; node++)
            {
                var outEdges = GetOutEdgeListHeader(node);

                writer.WriteCompact(outEdges.Count);

                int count = 0;
                foreach (var edge in GetOutgoingEdges(outEdges))
                {
                    edge.Serialize(writer);
                    count++;
                }

                Contract.Assert(outEdges.Count == count);
            }

            for (uint node = 1; node <= max; node++)
            {
                var nodeHeight = GetNodeHeight(node);
                writer.WriteCompact(nodeHeight);

                NodeEdgeListHeader inEdges = GetInEdgeListHeader(node);
                writer.WriteCompact(inEdges.Count);
            }
        }
Beispiel #2
0
 private Enumerator GetOutgoingEdges(NodeEdgeListHeader edges)
 {
     return(new Enumerator(this, edges.FirstIndex, edges.Count, m_enumeratorVerificationObject, isIncoming: false));
 }
Beispiel #3
0
        /// <summary>
        /// Loads this graph from a given binary stream.
        /// </summary>
        private void Load(BuildXLReader reader)
        {
            m_lastNodeId = (int)reader.ReadUInt32();
            m_edgeCount  = reader.ReadInt32();
            Contract.Assume(m_lastNodeId <= NodeId.MaxValue);

            // Create buffer with space for in edges and out edges
            m_edgeBuffer.Initialize(m_edgeCount * 2);
            int edgeIndex = 0;

            // Read the out edges
            {
                var accessor = m_edgeBuffer.GetAccessor();

                // TODO: This loop takes 70% of the deserialization time; make faster.
                for (uint i = 1; i <= m_lastNodeId; ++i)
                {
                    int outNodeCount   = reader.ReadInt32Compact();
                    int startEdgeIndex = edgeIndex;
                    for (int j = 0; j < outNodeCount; ++j)
                    {
                        var outgoingEdge = Edge.Deserialize(reader);
                        accessor[edgeIndex] = outgoingEdge;
                        edgeIndex++;
                    }

                    OutEdges[i] = new NodeEdgeListHeader(startEdgeIndex, outNodeCount);
                }
            }

            // Read the count of in edges
            // TODO: This loop takes 10% of the deserialization time; make faster.
            for (uint i = 1; i <= m_lastNodeId; i++)
            {
                int nodeHeight = reader.ReadInt32Compact();
                NodeHeights[i] = nodeHeight;

                int inEdgeCount = reader.ReadInt32Compact();

                // first edge index starts at end of edge span for this node and is decrements as edges
                // are discovered and added below. At the end the first edge index will
                // be at the beginning of the span
                edgeIndex += inEdgeCount;
                InEdges[i] = new NodeEdgeListHeader(edgeIndex, inEdgeCount);
            }

            // Write each out edge set to graph and compute the in edges
            // TODO: This parallel loop takes 20% of the (sequential) deserialization time; make faster.
            Parallel.For(1, m_lastNodeId + 1,
                         (i) =>
            {
                NodeId node  = new NodeId((uint)i);
                var accessor = m_edgeBuffer.GetAccessor();
                foreach (var e in GetOutgoingEdges(node))
                {
                    var inEdge = new Edge(node, e.IsLight);

                    // Note: We access the InEdges array element directly, not via the ConcurrentDenseIndex's indexer property.
                    // As a result, we mutate the actual array element, instead of a copy.
                    var p     = InEdges.GetBufferPointer(e.OtherNode.Value);
                    var index = p.Buffer[p.Index].InterlockedDecrementFirstIndex();

                    // Set the prior index and point header at that index. The initial value
                    // to index should be set to the index after the span. So this will always
                    // set an index within the edge span
                    accessor[index] = inEdge;
                }
            });
        }