<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vareti</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vareti"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Vareti"/>
	<updated>2026-09-18T16:13:58Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_E1525_TIAA&amp;diff=96158</id>
		<title>CSC/ECE 517 Spring 2015 E1525 TIAA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015_E1525_TIAA&amp;diff=96158"/>
		<updated>2015-04-01T00:09:21Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Test requirement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;font size=&amp;quot;6&amp;quot;&amp;gt;&amp;lt;b&amp;gt; Expertiza - Teaming information and analytics &amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
===Introduction To Expertiza===&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities.&amp;lt;ref&amp;gt;[https://github.com/expertiza/expertiza Expertiza on GitHub (Original version)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Motivation===&lt;br /&gt;
Expertiza is a large project developed as a combined effort of students and faculty using the Ruby on Rails framework. The main advantage of using Expertiza, in an educational environment, is for the instructor to introduce peer reviewing among the students. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and then review each other's assignments at the end. Expertiza supports submission of almost any document type, including the URLs and wiki pages.&lt;br /&gt;
Currently the teaming information is only accessible from specific assignment. Sometimes a course may require a student to work with at least, for example 5 other students. To check teaming information for a course, It would be helpful for a student to have a way in Expertiza to see how many other students (s)he has teamed with during a course, and who those students are.  An instructor might also want to see this information for grading purposes. Similarly, instructors and students want to see scores that teammates have given them for contributions to their team projects.&lt;br /&gt;
&lt;br /&gt;
===Scope===&lt;br /&gt;
New features added to the system will &lt;br /&gt;
&lt;br /&gt;
*Allow a student to see how many other students (s)he has teamed with during a course, and who those students are.&lt;br /&gt;
*Allow students to see the review score that teammates have given them for contributions to their team projects.&lt;br /&gt;
*Allow the instructor to be able to see the teaming information of all the students.&lt;br /&gt;
*Prevent students from seeing individual review scores when the number of team members who reviewed the student is &amp;lt; k, where k should be settable by the instructor when editing an assignment.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
All the documentation for the Expertiza system can be found in the following links:&lt;br /&gt;
[https://github.com/expertiza/expertiza Expertiza on Github]&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Wiki documentation for Expertiza]&lt;br /&gt;
&lt;br /&gt;
==Problem statements==&lt;br /&gt;
The following section discusses briefly about each file that has would be modified in the course of this project.&lt;br /&gt;
&lt;br /&gt;
==Use Cases==&lt;br /&gt;
&lt;br /&gt;
* '''Use Case 1: Allow a student to see how many other students (s)he has teamed with during a course, and who those students are.'''&lt;br /&gt;
** '''Actor:''' Student&lt;br /&gt;
** '''Actions:''' &lt;br /&gt;
*** Student logs in to Expertiza.&lt;br /&gt;
*** Open the “Teammates” link in the “Assignments” page to find the number of people the student has collaborated with till then.&lt;br /&gt;
&lt;br /&gt;
In order to achieve this, we plan to add a link, say “Teammates” in the “Assignments” page (http://expertiza.ncsu.edu/student_task/list). Clicking on the Teammates link leads to a page consisting of all the courses the student is enrolled in and number of people (s)he has teamed up with till then. This goal can be achieved by adding additional methods to the app/views/student_task/list.html.erb file and app/controllers/student_task_controller.rb.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Use Case 2: Allow students to see the review score that teammates have given them for contributions to their team projects.'''&lt;br /&gt;
** '''Actor:''' Student&lt;br /&gt;
** '''Actions:'''&lt;br /&gt;
*** Student logs in to Expertiza.&lt;br /&gt;
*** Open any assignment on the “Assignments” page.&lt;br /&gt;
*** Open “Your Scores” to find the review scores given by teammates in the “Teammate review” column.&lt;br /&gt;
&lt;br /&gt;
We noticed there is already a field “Teammate review” available in the “Your scores” (http://expertiza.ncsu.edu/grades/view_my_scores/&amp;lt;id&amp;gt;) page of each assignment, and as of now it seems to be unused. We plan to use this section for allowing the students to see their review scores given by the team mates. This can be achieved by making changes to the app/views/grades/_teammate_reviews.html.erb file.&lt;br /&gt;
&lt;br /&gt;
==Test requirement==&lt;br /&gt;
Testing Requirements&lt;br /&gt;
Testing will be carried out to verify the desired functionality. &lt;br /&gt;
For example:&lt;br /&gt;
A student have a new teammate in one of the course’s assignment. Then this student should be able to see this teammate on the teammates page for this course, not just on the teammates page for this assignment.&lt;br /&gt;
If this new teammate gave him a new review score based on his contribution to their teamwork, this student should be able to see the review score if the number of reviews given for this assignment is higher than k, which is preassigned by the instructor for this assignment. The review access condition is shown in the figure above.&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reference==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95505</id>
		<title>CSC/ECE 517 Spring 2015/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95505"/>
		<updated>2015-03-22T21:32:38Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1503. Refactor Leaderboard model, Leaderboard_helper and LeaderboardController classes'''&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the Expertiza based OSS project. This project aimed at refactoring the Leaderboard model, LeaderboardController, and Leaderboard_helper classes as per standard coding methodology for Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
'''Introduction to Expertiza'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system used to provide improved learning experience. Project is developed as a combined effort of students and faculty using the [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and then review each other's assignments at the end. Expertiza supports submission of almost any document type, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
Leaderboard is a module that can be used to find top three leaders in any class based on the score they have received on their submissions and reviews.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
&amp;lt;p&amp;gt;These class are responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generate a metric which aggregates peer review scores for all course assignments and then sorts individuals.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
&amp;lt;p&amp;gt;Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to single method. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper methods. Some snippets of code are redundant and have no effect on functionality. They can be removed.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Changes Made=&lt;br /&gt;
Leaderboard model was having public methods containing more than one feature in each method. We refactored such public methods in necessary public and private methods. Since we didn't create any new public method, we used the existing test cases to validate the changes. We removed helper methods from model class to respective helper class and changed all the references in model and controller classes.&lt;br /&gt;
==Leaderboard Model==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| model/Leaderboard#getParticipantsScore&lt;br /&gt;
| Refactored original method functionality into &amp;lt;br /&amp;gt;getAssignmentUniqueParticipantList,&amp;lt;br/&amp;gt;getAssignmentUniqueParticipantTeamList, &amp;lt;br/&amp;gt;getAggregatedAssignmentRevieweeList, &amp;lt;br/&amp;gt;getRevieweeListScore, and &amp;lt;br /&amp;gt;getUserScoreHashForCourse methods&lt;br /&gt;
| Many different features were originally written in one method. We refactored this method into many methods to achieve singularity.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#sortHash &amp;lt;br /&amp;gt; helpers/leaderboard_helper#sortHash&lt;br /&gt;
| Migrated method from Leaderboard model to leaderboard_helper class.&lt;br /&gt;
| sortHash is a helper method and is not explicit part of model class, hence it was moved to achieve code reusability and remove redundancy.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard scoreEntryScore parameter &lt;br /&gt;
| Parameter name is changed to entryScore&lt;br /&gt;
| The name was confusing. It was used to represent each entry's score, hence we changed the name to maintain readability of code.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
| Removed unwanted code snippets&lt;br /&gt;
| Redundant code snippet was found which has no affect on program.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
|Refactored method functionality and created private method, getCourseAccomplishmentHash&lt;br /&gt;
|More than one feature was implemented into one method. we split the functionality and remove code redundancy.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Controller==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| index&lt;br /&gt;
| Updated reference to sortHash method&lt;br /&gt;
| We moved sortHash method from model class to helper class. We updated all the old references for this method in index method on mentioned controller.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Re-factored Code Cases =&lt;br /&gt;
&lt;br /&gt;
===Methods added to leaderboard_model.rb===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # This method returns the unique participants for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantList(assignmentList)&lt;br /&gt;
    AssignmentParticipant.where(:parent_id =&amp;gt; assignmentList.pluck(:id)).uniq&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method returns the unique participant teams for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantTeamList(assignmentList)&lt;br /&gt;
    Team.where(&amp;quot;parent_id IN (?) AND type = ?&amp;quot;, assignmentList.pluck(:id), 'AssignmentTeam').uniq&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Before Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Get all participants of the assignment list&lt;br /&gt;
participantList = AssignmentParticipant.where(:parent_id =&amp;gt; assignmentList.pluck(:id)).uniq&lt;br /&gt;
&lt;br /&gt;
# Get all teams participated in the given assignment list.&lt;br /&gt;
teamList = Team.where(&amp;quot;parent_id IN (?) AND type = ?&amp;quot;, assignmentList.pluck(:id), 'AssignmentTeam').uniq&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, participantList, teamList)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, getAssignmentUniqueParticipantList(assignmentList), getAssignmentUniqueParticipantTeamList(assignmentList))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Private Methods added to leaderboard_model.rb===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  #All the methods below are private methods&lt;br /&gt;
  private&lt;br /&gt;
  #End result is a hash (qType =&amp;gt; (course =&amp;gt; (user =&amp;gt; score)))&lt;br /&gt;
  def Self.getUserScoreHashForCourse(scores,qTypeHash)&lt;br /&gt;
    for scoreEntry in scores&lt;br /&gt;
      revieweeUserIdList = Array.new&lt;br /&gt;
      if(assignmentMap[&amp;quot;team&amp;quot;].has_key?(scoreEntry.reviewee_id))&lt;br /&gt;
        # Reviewee is a team. Actual Reviewee will be users of the team.&lt;br /&gt;
        teamUserIds = TeamsUser.where(:team_id =&amp;gt; scoreEntry.reviewee_id).pluck(:user_id)&lt;br /&gt;
        revieweeUserIdList.concat(teamUserIds)&lt;br /&gt;
        courseId = assignmentMap[&amp;quot;team&amp;quot;][scoreEntry.reviewee_id].try(:course_id).to_i&lt;br /&gt;
      else&lt;br /&gt;
        # Reviewee is an individual participant.&lt;br /&gt;
        revieweeUserIdList &amp;lt;&amp;lt; assignmentMap[&amp;quot;participant&amp;quot;][scoreEntry.reviewee_id][&amp;quot;self&amp;quot;].try(:user_id)&lt;br /&gt;
        courseId = assignmentMap[&amp;quot;participant&amp;quot;][scoreEntry.reviewee_id][&amp;quot;assignment&amp;quot;].try(:course_id).to_i&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      questionnaireType = questionnaireResponseTypeHash[scoreEntry.object_type]&lt;br /&gt;
&lt;br /&gt;
      addScoreToResultantHash(qTypeHash, questionnaireType, courseId, revieweeUserIdList, scoreEntry.score)&lt;br /&gt;
    end&lt;br /&gt;
    qTypeHash&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def Self.getRevieweeListScore(revieweeList,questionnaireResponseTypeHash)&lt;br /&gt;
    ScoreCache.where(&amp;quot;reviewee_id IN (?) and object_type IN (?)&amp;quot;, revieweeList, questionnaireResponseTypeHash.keys)&lt;br /&gt;
  end&lt;br /&gt;
  # Aggregate total reviewee list for an assignment&lt;br /&gt;
  def Self.getAggregatedAssignmentRevieweeList(assignmentList)&lt;br /&gt;
    revieweeList=Array.new&lt;br /&gt;
    revieweeList= getAssignmentUniqueParticipantTeamList(assignmentList).pluck(:id)&lt;br /&gt;
    revieweeList.concat(getAssignmentUniqueParticipantTeamList(assignmentList).pluck(:id)).uniq!&lt;br /&gt;
&lt;br /&gt;
  end&lt;br /&gt;
  # This method returns the unique participants for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantList(assignmentList)&lt;br /&gt;
    AssignmentParticipant.where(:parent_id =&amp;gt; assignmentList.pluck(:id)).uniq&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method returns the unique participant teams for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantTeamList(assignmentList)&lt;br /&gt;
    Team.where(&amp;quot;parent_id IN (?) AND type = ?&amp;quot;, assignmentList.pluck(:id), 'AssignmentTeam').uniq&lt;br /&gt;
  end&lt;br /&gt;
  #All the methods till here are private methods&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===New method added to leaderboard_helper.rb===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # This method does a destructive sort on the computed scores hash so&lt;br /&gt;
  # that it can be mined for personal achievement information&lt;br /&gt;
  def self.sortHash(qTypeHash)&lt;br /&gt;
    result = Hash.new&lt;br /&gt;
    # Deep-copy of Hash&lt;br /&gt;
    result = Marshal.load(Marshal.dump(qTypeHash))&lt;br /&gt;
&lt;br /&gt;
    result.each { |qType, courseHash|&lt;br /&gt;
      courseHash.each { |courseId, userScoreHash|&lt;br /&gt;
        userScoreSortArray = userScoreHash.sort { |a, b| b[1][0] &amp;lt;=&amp;gt; a[1][0]}&lt;br /&gt;
        result[qType][courseId] = userScoreSortArray&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    result&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Method removed from leaderboard_model.rb===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # This method does a destructive sort on the computed scores hash so&lt;br /&gt;
  # that it can be mined for personal achievement information&lt;br /&gt;
  def self.sortHash(qTypeHash)&lt;br /&gt;
    result = Hash.new&lt;br /&gt;
    # Deep-copy of Hash&lt;br /&gt;
    result = Marshal.load(Marshal.dump(qTypeHash))&lt;br /&gt;
&lt;br /&gt;
    result.each { |qType, courseHash|&lt;br /&gt;
      courseHash.each { |courseId, userScoreHash|&lt;br /&gt;
        userScoreSortArray = userScoreHash.sort { |a, b| b[1][0] &amp;lt;=&amp;gt; a[1][0]}&lt;br /&gt;
        result[qType][courseId] = userScoreSortArray&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    result&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Before Refactoring===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.addScoreToResultantHash(qTypeHash, questionnaireType, courseId, revieweeUserIdList, scoreEntryScore)&lt;br /&gt;
&lt;br /&gt;
  userHash[revieweeUserId] = [scoreEntryScore, 1]&lt;br /&gt;
&lt;br /&gt;
  qTypeHash[questionnaireType][courseId][revieweeUserId] = [scoreEntryScore, 1]&lt;br /&gt;
&lt;br /&gt;
  currentUserScore[0] = (currentTotalScore + scoreEntryScore) / currentUserScore[1]&lt;br /&gt;
&lt;br /&gt;
  csSortedHash = Leaderboard.sortHash(csHash)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Refactoring===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.addScoreToResultantHash(qTypeHash, questionnaireType, courseId, revieweeUserIdList, entryScore)&lt;br /&gt;
&lt;br /&gt;
  userHash[revieweeUserId] = [entryScore, 1]&lt;br /&gt;
&lt;br /&gt;
  qTypeHash[questionnaireType][courseId][revieweeUserId] = [entryScore, 1]&lt;br /&gt;
&lt;br /&gt;
  currentUserScore[0] = (currentTotalScore + entryScore) / currentUserScore[1]&lt;br /&gt;
&lt;br /&gt;
  csSortedHash = LeaderboardHelper.sortHash(csHash)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===New method added to leaderboard_helper.rb===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # This method returns course accomplishment hash for a user&lt;br /&gt;
  def self.getCourseAccomplishmentHash(courseIdList,accomplishmentMap,userId,csHash)&lt;br /&gt;
    courseAccomplishmentHash = Hash.new&lt;br /&gt;
    csSortedHash = LeaderboardHelper.sortHash(csHash)&lt;br /&gt;
&lt;br /&gt;
    for courseId in courseIdList&lt;br /&gt;
      for accomplishment in accomplishmentMap.keys&lt;br /&gt;
        # Get score for current questionnaireType/accomplishment, courseId and userId from csHash&lt;br /&gt;
        score = csHash.fetch(accomplishment, {}).fetch(courseId, {}).fetch(userId, nil)&lt;br /&gt;
        if(score)&lt;br /&gt;
          if courseAccomplishmentHash[courseId].nil?&lt;br /&gt;
            courseAccomplishmentHash[courseId] = Array.new&lt;br /&gt;
          end&lt;br /&gt;
          # Calculate rank of current user&lt;br /&gt;
          rank = 1 + csSortedHash[accomplishment][courseId].index([userId, score])&lt;br /&gt;
          total = csSortedHash[accomplishment][courseId].length&lt;br /&gt;
&lt;br /&gt;
          courseAccomplishmentHash[courseId] &amp;lt;&amp;lt; {:accomp =&amp;gt; accomplishmentMap[accomplishment],&lt;br /&gt;
                                                 :score =&amp;gt; score[0],&lt;br /&gt;
                                                 :rankStr =&amp;gt; &amp;quot;#{rank} of #{total}&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    courseAccomplishmentHash&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Before Refactoring===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    csSortedHash = LeaderboardHelper.sortHash(csHash)&lt;br /&gt;
&lt;br /&gt;
    for courseId in courseIdList&lt;br /&gt;
      for accomplishment in accomplishmentMap.keys&lt;br /&gt;
        # Get score for current questionnaireType/accomplishment, courseId and userId from csHash&lt;br /&gt;
        score = csHash.fetch(accomplishment, {}).fetch(courseId, {}).fetch(userId, nil)&lt;br /&gt;
        if(score)&lt;br /&gt;
          if courseAccomplishmentHash[courseId].nil?&lt;br /&gt;
            courseAccomplishmentHash[courseId] = Array.new&lt;br /&gt;
          end&lt;br /&gt;
          # Calculate rank of current user&lt;br /&gt;
          rank = 1 + csSortedHash[accomplishment][courseId].index([userId, score])&lt;br /&gt;
          total = csSortedHash[accomplishment][courseId].length&lt;br /&gt;
&lt;br /&gt;
          courseAccomplishmentHash[courseId] &amp;lt;&amp;lt; {:accomp =&amp;gt; accomplishmentMap[accomplishment],&lt;br /&gt;
                                                 :score =&amp;gt; score[0],&lt;br /&gt;
                                                 :rankStr =&amp;gt; &amp;quot;#{rank} of #{total}&amp;quot;&lt;br /&gt;
          }&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    courseAccomplishmentHash&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Refactoring===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  return getCourseAccomplishmentHash(courseIdList,accomplishmentMap,userId,csHash)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Changes made to leaderboard_controller.rb==&lt;br /&gt;
&lt;br /&gt;
===Before===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@csHash = Leaderboard.sortHash(@csHash)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@csHash = LeaderboardHelper.sortHash(@csHash)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Steps to verify changes manually=&lt;br /&gt;
&lt;br /&gt;
=Automated Tests=&lt;br /&gt;
&lt;br /&gt;
===Unit test===&lt;br /&gt;
We didn't create any new public method as part of this project, instead we refactored the existing code. Existing test suit was suitable for testing our modifications.&lt;br /&gt;
&lt;br /&gt;
=See Also=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References=&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95489</id>
		<title>CSC/ECE 517 Spring 2015/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95489"/>
		<updated>2015-03-22T21:19:31Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1503. Refactor Leaderboard model, Leaderboard_helper and LeaderboardController classes'''&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the Expertiza based OSS project. This project aimed at refactoring the Leaderboard model, LeaderboardController, and Leaderboard_helper classes as per standard coding methodology for Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
'''Introduction to Expertiza'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system used to provide improved learning experience. Project is developed as a combined effort of students and faculty using the [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and then review each other's assignments at the end. Expertiza supports submission of almost any document type, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
Leaderboard is a module that can be used to find top three leaders in any class based on the score they have received on their submissions and reviews.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
&amp;lt;p&amp;gt;These class are responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generate a metric which aggregates peer review scores for all course assignments and then sorts individuals.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
&amp;lt;p&amp;gt;Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to single function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Changes Made=&lt;br /&gt;
Leaderboard model was having public methods containing more than one feature in each method. We refactored such public methods in necessary public and private methods. Since we didn't create any new public method, we used the existing test cases to validate the changes. We removed helper methods from model class to respective helper class and changed all the references in model and controller classes.&lt;br /&gt;
==Leaderboard Model==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| model/Leaderboard#getParticipantsScore&lt;br /&gt;
| Refactored original method functionality into &amp;lt;br /&amp;gt;getAssignmentUniqueParticipantList,&amp;lt;br/&amp;gt;getAssignmentUniqueParticipantTeamList, &amp;lt;br/&amp;gt;getAggregatedAssignmentRevieweeList, &amp;lt;br/&amp;gt;getRevieweeListScore, and &amp;lt;br /&amp;gt;getUserScoreHashForCourse methods&lt;br /&gt;
| Many different features were originally written in one method. We refactored this method into many methods to achieve singularity.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#sortHash &amp;lt;br /&amp;gt; helpers/leaderboard_helper#sortHash&lt;br /&gt;
| Migrated method from Leaderboard model to leaderboard_helper class.&lt;br /&gt;
| sortHash is a helper method and is not explicit part of model class, hence it was moved to achieve code reusability and remove redundancy.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard scoreEntryScore parameter &lt;br /&gt;
| Parameter name is changed to entryScore&lt;br /&gt;
| The name was confusing. It was used to represent each entry's score, hence we changed the name to maintain readability of code.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
| Removed unwanted code snippets&lt;br /&gt;
| Redundant code snippet was found which has no affect on program.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
|Refactored method functionality and created private method, getCourseAccomplishmentHash&lt;br /&gt;
|More than one feature was implemented into one method. we split the functionality and remove code redundancy.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Controller==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| index&lt;br /&gt;
| Updated reference to sortHash method&lt;br /&gt;
| We moved sortHash method from model class to helper class. We updated all the old references for this method in index method on mentioned controller.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Re-factored Code Cases =&lt;br /&gt;
&lt;br /&gt;
== Case 1 : Refactoring ... == &lt;br /&gt;
&lt;br /&gt;
===Functions added===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # This method returns the unique participants for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantList(assignmentList)&lt;br /&gt;
    AssignmentParticipant.where(:parent_id =&amp;gt; assignmentList.pluck(:id)).uniq&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method returns the unique participant teams for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantTeamList(assignmentList)&lt;br /&gt;
    Team.where(&amp;quot;parent_id IN (?) AND type = ?&amp;quot;, assignmentList.pluck(:id), 'AssignmentTeam').uniq&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Before Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, participantList, teamList)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, getAssignmentUniqueParticipantList(assignmentList), getAssignmentUniqueParticipantTeamList(assignmentList))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Case 2 :  ==&lt;br /&gt;
&lt;br /&gt;
=Steps to verify changes manually=&lt;br /&gt;
&lt;br /&gt;
===User2 Role===&lt;br /&gt;
&lt;br /&gt;
=Automated Tests=&lt;br /&gt;
&lt;br /&gt;
===Unit test===&lt;br /&gt;
&lt;br /&gt;
===Integration (Cucumber) tests===&lt;br /&gt;
&lt;br /&gt;
=See Also=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References=&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95487</id>
		<title>CSC/ECE 517 Spring 2015/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95487"/>
		<updated>2015-03-22T21:17:47Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1503. Refactor Leaderboard model, Leaderboard_helper and LeaderboardController classes'''&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the Expertiza based OSS project. This project aimed at refactoring the Leaderboard model, LeaderboardController, and Leaderboard_helper classes as per standard coding methodology for Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
'''Introduction to Expertiza'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system used to provide improved learning experience. Project is developed as a combined effort of students and faculty using the [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and then review each other's assignments at the end. Expertiza supports submission of almost any document type, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
Leaderboard is a module that can be used to find top three leaders in any class based on the score they have received on their submissions and reviews.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
&amp;lt;p&amp;gt;This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
&amp;lt;p&amp;gt;Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to single function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Changes Made=&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Model==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| model/Leaderboard#getParticipantsScore&lt;br /&gt;
| Refactored original method functionality into &amp;lt;br /&amp;gt;getAssignmentUniqueParticipantList,&amp;lt;br/&amp;gt;getAssignmentUniqueParticipantTeamList, &amp;lt;br/&amp;gt;getAggregatedAssignmentRevieweeList, &amp;lt;br/&amp;gt;getRevieweeListScore, and &amp;lt;br /&amp;gt;getUserScoreHashForCourse methods&lt;br /&gt;
| Many different features were originally written in one method. We refactored this method into many methods to achieve singularity.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#sortHash &amp;lt;br /&amp;gt; helpers/leaderboard_helper#sortHash&lt;br /&gt;
| Migrated method from Leaderboard model to leaderboard_helper class.&lt;br /&gt;
| sortHash is a helper method and is not explicit part of model class, hence it was moved to achieve code reusability and remove redundancy.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard scoreEntryScore parameter &lt;br /&gt;
| Parameter name is changed to entryScore&lt;br /&gt;
| The name was confusing. It was used to represent each entry's score, hence we changed the name to maintain readability of code.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
| Removed unwanted code snippets&lt;br /&gt;
| Redundant code snippet was found which has no affect on program.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
|Refactored method functionality and created private method, getCourseAccomplishmentHash&lt;br /&gt;
|More than one feature was implemented into one method. we split the functionality and remove code redundancy.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Controller==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| index&lt;br /&gt;
| Updated reference to sortHash method&lt;br /&gt;
| We moved sortHash method from model class to helper class. We updated all the old references for this method in index method on mentioned controller.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Re-factored Code Cases =&lt;br /&gt;
&lt;br /&gt;
== Case 1 : Refactoring ... == &lt;br /&gt;
&lt;br /&gt;
===Functions added===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # This method returns the unique participants for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantList(assignmentList)&lt;br /&gt;
    AssignmentParticipant.where(:parent_id =&amp;gt; assignmentList.pluck(:id)).uniq&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method returns the unique participant teams for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantTeamList(assignmentList)&lt;br /&gt;
    Team.where(&amp;quot;parent_id IN (?) AND type = ?&amp;quot;, assignmentList.pluck(:id), 'AssignmentTeam').uniq&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Before Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, participantList, teamList)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, getAssignmentUniqueParticipantList(assignmentList), getAssignmentUniqueParticipantTeamList(assignmentList))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Case 2 :  ==&lt;br /&gt;
&lt;br /&gt;
=Steps to verify changes manually=&lt;br /&gt;
&lt;br /&gt;
===User2 Role===&lt;br /&gt;
&lt;br /&gt;
=Automated Tests=&lt;br /&gt;
&lt;br /&gt;
===Unit test===&lt;br /&gt;
&lt;br /&gt;
===Integration (Cucumber) tests===&lt;br /&gt;
&lt;br /&gt;
=See Also=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References=&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95486</id>
		<title>CSC/ECE 517 Spring 2015/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95486"/>
		<updated>2015-03-22T21:17:10Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1503. Refactor Leaderboard model, Leaderboard_helper and LeaderboardController classes'''&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the Expertiza based OSS project. This project aimed at refactoring the Leaderboard model, LeaderboardController, and Leaderboard_helper classes as per standard coding methodology for Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
'''Introduction to Expertiza'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system used to provide improved learning experience. Project is developed as a combined effort of students and faculty using the [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and then review each other's assignments at the end. Expertiza supports submission of almost any document type, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
Leaderboard is a module that can be used to find top three leaders in any class based on the score they have received on their submissions and reviews.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
&amp;lt;p&amp;gt;This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
&amp;lt;p&amp;gt;Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Changes Made=&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Model==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| model/Leaderboard#getParticipantsScore&lt;br /&gt;
| Refactored original method functionality into &amp;lt;br /&amp;gt;getAssignmentUniqueParticipantList,&amp;lt;br/&amp;gt;getAssignmentUniqueParticipantTeamList, &amp;lt;br/&amp;gt;getAggregatedAssignmentRevieweeList, &amp;lt;br/&amp;gt;getRevieweeListScore, and &amp;lt;br /&amp;gt;getUserScoreHashForCourse methods&lt;br /&gt;
| Many different features were originally written in one method. We refactored this method into many methods to achieve singularity.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#sortHash &amp;lt;br /&amp;gt; helpers/leaderboard_helper#sortHash&lt;br /&gt;
| Migrated method from Leaderboard model to leaderboard_helper class.&lt;br /&gt;
| sortHash is a helper method and is not explicit part of model class, hence it was moved to achieve code reusability and remove redundancy.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard scoreEntryScore parameter &lt;br /&gt;
| Parameter name is changed to entryScore&lt;br /&gt;
| The name was confusing. It was used to represent each entry's score, hence we changed the name to maintain readability of code.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
| Removed unwanted code snippets&lt;br /&gt;
| Redundant code snippet was found which has no affect on program.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
|Refactored method functionality and created private method, getCourseAccomplishmentHash&lt;br /&gt;
|More than one feature was implemented into one method. we split the functionality and remove code redundancy.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Controller==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| index&lt;br /&gt;
| Updated reference to sortHash method&lt;br /&gt;
| We moved sortHash method from model class to helper class. We updated all the old references for this method in index method on mentioned controller.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Re-factored Code Cases =&lt;br /&gt;
&lt;br /&gt;
== Case 1 : Refactoring ... == &lt;br /&gt;
&lt;br /&gt;
===Functions added===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # This method returns the unique participants for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantList(assignmentList)&lt;br /&gt;
    AssignmentParticipant.where(:parent_id =&amp;gt; assignmentList.pluck(:id)).uniq&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method returns the unique participant teams for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantTeamList(assignmentList)&lt;br /&gt;
    Team.where(&amp;quot;parent_id IN (?) AND type = ?&amp;quot;, assignmentList.pluck(:id), 'AssignmentTeam').uniq&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Before Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, participantList, teamList)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, getAssignmentUniqueParticipantList(assignmentList), getAssignmentUniqueParticipantTeamList(assignmentList))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Case 2 :  ==&lt;br /&gt;
&lt;br /&gt;
=Steps to verify changes manually=&lt;br /&gt;
&lt;br /&gt;
===User2 Role===&lt;br /&gt;
&lt;br /&gt;
=Automated Tests=&lt;br /&gt;
&lt;br /&gt;
===Unit test===&lt;br /&gt;
&lt;br /&gt;
===Integration (Cucumber) tests===&lt;br /&gt;
&lt;br /&gt;
=See Also=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References=&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95485</id>
		<title>CSC/ECE 517 Spring 2015/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95485"/>
		<updated>2015-03-22T21:16:55Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1503. Refactor Leaderboard model, Leaderboard_helper and LeaderboardController classes'''&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the Expertiza based OSS project. This project aimed at refactoring the Leaderboard model, LeaderboardController, and Leaderboard_helper classes as per standard coding methodology for Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
'''Introduction to Expertiza'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system used to provide improved learning experience. Project is developed as a combined effort of students and faculty using the [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and then review each other's assignments at the end. Expertiza supports submission of almost any document type, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
Leaderboard is a module that can be used to find top three leaders in any class based on the score they have received on their submissions and reviews.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==== Project Description ====&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
&amp;lt;p&amp;gt;This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
&amp;lt;p&amp;gt;Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Changes Made=&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Model==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| model/Leaderboard#getParticipantsScore&lt;br /&gt;
| Refactored original method functionality into &amp;lt;br /&amp;gt;getAssignmentUniqueParticipantList,&amp;lt;br/&amp;gt;getAssignmentUniqueParticipantTeamList, &amp;lt;br/&amp;gt;getAggregatedAssignmentRevieweeList, &amp;lt;br/&amp;gt;getRevieweeListScore, and &amp;lt;br /&amp;gt;getUserScoreHashForCourse methods&lt;br /&gt;
| Many different features were originally written in one method. We refactored this method into many methods to achieve singularity.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#sortHash &amp;lt;br /&amp;gt; helpers/leaderboard_helper#sortHash&lt;br /&gt;
| Migrated method from Leaderboard model to leaderboard_helper class.&lt;br /&gt;
| sortHash is a helper method and is not explicit part of model class, hence it was moved to achieve code reusability and remove redundancy.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard scoreEntryScore parameter &lt;br /&gt;
| Parameter name is changed to entryScore&lt;br /&gt;
| The name was confusing. It was used to represent each entry's score, hence we changed the name to maintain readability of code.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
| Removed unwanted code snippets&lt;br /&gt;
| Redundant code snippet was found which has no affect on program.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
|Refactored method functionality and created private method, getCourseAccomplishmentHash&lt;br /&gt;
|More than one feature was implemented into one method. we split the functionality and remove code redundancy.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Controller==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| index&lt;br /&gt;
| Updated reference to sortHash method&lt;br /&gt;
| We moved sortHash method from model class to helper class. We updated all the old references for this method in index method on mentioned controller.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Re-factored Code Cases =&lt;br /&gt;
&lt;br /&gt;
== Case 1 : Refactoring ... == &lt;br /&gt;
&lt;br /&gt;
===Functions added===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  # This method returns the unique participants for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantList(assignmentList)&lt;br /&gt;
    AssignmentParticipant.where(:parent_id =&amp;gt; assignmentList.pluck(:id)).uniq&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method returns the unique participant teams for assignment list.&lt;br /&gt;
  def self.getAssignmentUniqueParticipantTeamList(assignmentList)&lt;br /&gt;
    Team.where(&amp;quot;parent_id IN (?) AND type = ?&amp;quot;, assignmentList.pluck(:id), 'AssignmentTeam').uniq&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Before Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, participantList, teamList)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Refactoring===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assignmentMap = getAssignmentMapping(assignmentList, getAssignmentUniqueParticipantList(assignmentList), getAssignmentUniqueParticipantTeamList(assignmentList))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Case 2 :  ==&lt;br /&gt;
&lt;br /&gt;
=Steps to verify changes manually=&lt;br /&gt;
&lt;br /&gt;
===User2 Role===&lt;br /&gt;
&lt;br /&gt;
=Automated Tests=&lt;br /&gt;
&lt;br /&gt;
===Unit test===&lt;br /&gt;
&lt;br /&gt;
===Integration (Cucumber) tests===&lt;br /&gt;
&lt;br /&gt;
=See Also=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References=&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95484</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95484"/>
		<updated>2015-03-22T21:16:37Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== Project Description ====&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
&amp;lt;p&amp;gt;This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
&amp;lt;p&amp;gt;Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95483</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95483"/>
		<updated>2015-03-22T21:16:18Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== Project Description ====&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
&amp;lt;p&amp;gt;This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95482</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95482"/>
		<updated>2015-03-22T21:15:59Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* What needs to be don */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== Project Description ====&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done'''&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95481</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95481"/>
		<updated>2015-03-22T21:15:46Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* What they do */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== Project Description ====&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
====What needs to be don====&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95480</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95480"/>
		<updated>2015-03-22T21:15:26Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== Project Description ====&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
====What they do====&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
====What needs to be don====&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95479</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95479"/>
		<updated>2015-03-22T21:14:43Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==== Project Description ====&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
'''What needs to be don'''&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95476</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95476"/>
		<updated>2015-03-22T21:13:55Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* What needs to be done */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
'''What needs to be don'''&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95475</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95475"/>
		<updated>2015-03-22T21:13:42Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* What they do */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do'''&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
=What needs to be done=&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95474</id>
		<title>CSC/ECE 517 Spring 1989/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_1989/oss_E1503_RSA&amp;diff=95474"/>
		<updated>2015-03-22T21:13:13Z</updated>

		<summary type="html">&lt;p&gt;Vareti: Created page with &amp;quot;= Project Description = '''Classes involved:'''  leaderboard.rb  leaderboard_controller.rb  '''Modules involved: '''  leaderboard_helper.rb  =What they do=  This class is respons...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
=What they do=&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
=What needs to be done=&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95472</id>
		<title>CSC/ECE 517 Spring 2015/oss E1503 RSA</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2015/oss_E1503_RSA&amp;diff=95472"/>
		<updated>2015-03-22T21:12:13Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Problem Statement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1503. Refactor Leaderboard model, Leaderboard_helper and LeaderboardController classes'''&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the Expertiza based OSS project. This project aimed at refactoring the Leaderboard model, LeaderboardController, and Leaderboard_helper classes as per standard coding methodology for Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
'''Introduction to Expertiza'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a peer review based system used to provide improved learning experience. Project is developed as a combined effort of students and faculty using the [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create and customize assignments, create a list of topics the students can sign up for, have students work on teams and then review each other's assignments at the end. Expertiza supports submission of almost any document type, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
Leaderboard is a module that can be used to find top three leaders in any class based on the score they have received on their submissions and reviews.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Project Description =&lt;br /&gt;
'''Classes involved:'''&lt;br /&gt;
 leaderboard.rb&lt;br /&gt;
 leaderboard_controller.rb&lt;br /&gt;
&lt;br /&gt;
'''Modules involved: '''&lt;br /&gt;
 leaderboard_helper.rb&lt;br /&gt;
&lt;br /&gt;
'''What they do:'''&lt;br /&gt;
 This class is responsible for calculating top 3 individuals which is to be displayed as the leaderboard for the class and generates a metric which aggregates peer review scores for all course assignments and then sorts individuals.&lt;br /&gt;
&lt;br /&gt;
'''What needs to be done:'''&lt;br /&gt;
 Methods like &amp;lt;i&amp;gt;getParticipantsScore&amp;lt;/i&amp;gt; and &amp;lt;i&amp;gt;extractPersonalAchievements&amp;lt;/i&amp;gt; needs to be refactored as these single functions have multiple responsibilities. They can be modularized delegating single resposibility to one function. &amp;lt;i&amp;gt;sortHash&amp;lt;/i&amp;gt; method is not an explicit leaderboard model and can be moved to helper functions. Some snippets of code are redundant and have no effect on functionality. They can be removed.&lt;br /&gt;
&lt;br /&gt;
=Changes Made=&lt;br /&gt;
&lt;br /&gt;
==Leaderboard Model==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| model/Leaderboard#getParticipantsScore&lt;br /&gt;
| Refactored original method functionality into &amp;lt;br /&amp;gt;getAssignmentUniqueParticipantList,&amp;lt;br/&amp;gt;getAssignmentUniqueParticipantTeamList, &amp;lt;br/&amp;gt;getAggregatedAssignmentRevieweeList, &amp;lt;br/&amp;gt;getRevieweeListScore, and &amp;lt;br /&amp;gt;getUserScoreHashForCourse methods&lt;br /&gt;
| Many different features were originally written in one method. We refactored this method into many methods to achieve singularity.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#sortHash &amp;lt;br /&amp;gt; helpers/leaderboard_helper#sortHash&lt;br /&gt;
| Migrated method from Leaderboard model to leaderboard_helper class.&lt;br /&gt;
| sortHash is a helper method and is not explicit part of model class, hence it was moved to achieve code reusability and remove redundancy.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard scoreEntryScore parameter &lt;br /&gt;
| Parameter name is changed to entryScore&lt;br /&gt;
| The name was confusing. It was used to represent each entry's score, hence we changed the name to maintain readability of code.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
| Removed unwanted code snippets&lt;br /&gt;
| Redundant code snippet was found which has no affect on program.&lt;br /&gt;
|-&lt;br /&gt;
| model/Leaderboard#extractPersonalAchievements&lt;br /&gt;
|Refactored method functionality and created private method, getCourseAccomplishmentHash&lt;br /&gt;
|More than one feature was implemented into one method. we split the functionality and remove code redundancy.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Bookmark Controller==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| create&lt;br /&gt;
| ----------------&lt;br /&gt;
| -----------&lt;br /&gt;
|-&lt;br /&gt;
| update&lt;br /&gt;
| -----------------&lt;br /&gt;
| --------&lt;br /&gt;
|-&lt;br /&gt;
| edit&lt;br /&gt;
| --------------&lt;br /&gt;
| ---------&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; valign=&amp;quot;middle&amp;quot; |&lt;br /&gt;
destroy&lt;br /&gt;
| -----------------&lt;br /&gt;
| ---------&lt;br /&gt;
|-&lt;br /&gt;
| ---------------&lt;br /&gt;
| ----------&lt;br /&gt;
|-&lt;br /&gt;
| ----------&lt;br /&gt;
| ----------&lt;br /&gt;
|}&lt;br /&gt;
==Views==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width:13%;&amp;quot;|Method Name&lt;br /&gt;
! style=&amp;quot;width:33%;&amp;quot;|Changes Made &lt;br /&gt;
! style=&amp;quot;width:43%;&amp;quot;|Reason For Change&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| bookmarks/_result.html.erb&lt;br /&gt;
| ----------------&lt;br /&gt;
| -----------&lt;br /&gt;
|-&lt;br /&gt;
| bookmarks/search_bookmarks.html.erb&lt;br /&gt;
| -----------------&lt;br /&gt;
| --------&lt;br /&gt;
|-&lt;br /&gt;
| bookmarks/view_bookmarks.html.erb&lt;br /&gt;
| --------------&lt;br /&gt;
| ---------&lt;br /&gt;
|-&lt;br /&gt;
| bookmarks/_searchmine.html.erb&lt;br /&gt;
| -----------------&lt;br /&gt;
| ---------&lt;br /&gt;
|-&lt;br /&gt;
| bookmarks/add_bookmark_form.html.erb&lt;br /&gt;
| -----------------&lt;br /&gt;
| ---------&lt;br /&gt;
|-&lt;br /&gt;
| bookmarks/edit_bookmark_form.html.erb&lt;br /&gt;
| -----------------&lt;br /&gt;
| ---------&lt;br /&gt;
|-&lt;br /&gt;
| bookmarks/managing_bookmarks.html.erb&lt;br /&gt;
| -----------------&lt;br /&gt;
| ---------&lt;br /&gt;
|-&lt;br /&gt;
| layouts/application.html.erb&lt;br /&gt;
| -----------------&lt;br /&gt;
| ---------&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Re-factored Code Cases =&lt;br /&gt;
&lt;br /&gt;
== Case 1 : Refactoring add_this_bookmark and add_topic_bookmark ==&lt;br /&gt;
&lt;br /&gt;
The consistency of these two methods shows plenty of repetitive code. In order to effectively refactor these methods and reuse the code they both need, our team merged the two methods together by enabling add_this_bookmark method to handle creation of a bookmark when a topic id is provided (main functionality of add_topic_bookmark method). Once we implemented this change on add_this_bookmark method, we deleted add_topic_bookmark method as it became obsolete. Therefore, we retained the same functionality while reducing the method by 7 repetitive lines of code. &lt;br /&gt;
&lt;br /&gt;
===Before Changes===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_topic_bookmark(b_url, b_title, b_tags_text, b_description,session_user, topicid)&lt;br /&gt;
    # Check if the bookmark exists and add / edit based on that&lt;br /&gt;
    bookmark_exists = check_bookmark_exists(b_url)&lt;br /&gt;
    bmapping_exists = check_bmapping_exists(b_url,session_user)&lt;br /&gt;
    if (!bookmark_exists || !bmapping_exists)&lt;br /&gt;
      Bookmark.add_bookmark(b_url, b_title, b_tags_text, b_description,session_user,topicid)&lt;br /&gt;
    elsif (bmapping_exists)&lt;br /&gt;
      Bookmark.edit_this_bookmark(b_url, b_title, b_tags_text, b_description,session_user)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.add_this_bookmark(b_url, b_title, b_tags_text, b_description,session_user)&lt;br /&gt;
    bookmark_exists = check_bookmark_exists(b_url)&lt;br /&gt;
    bmapping_exists = check_bmapping_exists(b_url,session_user)&lt;br /&gt;
    if (!bookmark_exists || !bmapping_exists)&lt;br /&gt;
      Bookmark.add_bookmark(b_url, b_title, b_tags_text, b_description,session_user)&lt;br /&gt;
    elsif (bmapping_exists)&lt;br /&gt;
      Bookmark.edit_this_bookmark(b_url, b_title, b_tags_text, b_description,session_user)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===After Changes===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.add_this_bookmark(b_url, b_title, b_tags_text, b_description,session_user, topic_id)&lt;br /&gt;
    bookmark_exists = check_bookmark_exists(b_url)&lt;br /&gt;
    bmapping_exists = check_bmapping_exists(b_url,session_user)&lt;br /&gt;
    if (!bookmark_exists || !bmapping_exists)&lt;br /&gt;
      if(topic_id) # something has been passed for topic_id&lt;br /&gt;
        Bookmark.add_bookmark(b_url, b_title, b_tags_text, b_description,session_user,topic_id)&lt;br /&gt;
      else&lt;br /&gt;
        Bookmark.add_bookmark(b_url, b_title, b_tags_text, b_description,session_user, nil)&lt;br /&gt;
      end&lt;br /&gt;
    elsif (bmapping_exists)&lt;br /&gt;
      Bookmark.edit(b_url, b_title, b_tags_text, b_description,session_user)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Case 2 :  ==&lt;br /&gt;
&lt;br /&gt;
=Steps to verify changes manually=&lt;br /&gt;
&lt;br /&gt;
===User2 Role===&lt;br /&gt;
&lt;br /&gt;
=Automated Tests=&lt;br /&gt;
&lt;br /&gt;
===Unit test===&lt;br /&gt;
&lt;br /&gt;
===Integration (Cucumber) tests===&lt;br /&gt;
&lt;br /&gt;
=See Also=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References=&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94793</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94793"/>
		<updated>2015-03-05T17:31:45Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Graphs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Linked_list linked lists] is a data structure which contains a set of nodes. Nodes in linked list are composed of data and references to next node. It is the simplest form of linked data structures. Other linked data structures include Trees, Hash Tables and Graphs. One component that tends to link together various linked data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine the paths.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With [http://en.wikipedia.org/wiki/Linked_list linked lists], there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
        parallel begin&lt;br /&gt;
            Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
            Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
        parallel end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
    Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
        parbegin&lt;br /&gt;
            Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
            Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
            /* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
            hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
            /* Phase 2. Build partial lists */&lt;br /&gt;
            Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
        parend;&lt;br /&gt;
    Step 2. Link up partial lists.&lt;br /&gt;
        /* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
        P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
        /* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
        for each of the p blocks do&lt;br /&gt;
            for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
            parbegin&lt;br /&gt;
                for i := 1 to (n/p^2) do&lt;br /&gt;
                begin&lt;br /&gt;
                    Pi is given at most a node mi in each iteration.&lt;br /&gt;
                    if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
                    then&lt;br /&gt;
                        if the global list for the level of node mi is empty&lt;br /&gt;
                        then&lt;br /&gt;
                            let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
                        else&lt;br /&gt;
                            list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
                        end;&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
                    if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 4. Obtain ranking&lt;br /&gt;
        LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
    Step 5. Output the result&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
            parend;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
    g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
    g.mark(false);          // unmark the whole graph&lt;br /&gt;
    refresh(null);          // and redraw it&lt;br /&gt;
    Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
    g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
    java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
    queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
    while(!queue.isEmpty())&lt;br /&gt;
    {&lt;br /&gt;
        Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
        queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
        g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
        int dp = g.degreePlus(u);&lt;br /&gt;
        for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
        {&lt;br /&gt;
            Vertex v = g.ithSucc(i, u);&lt;br /&gt;
            if(Color.white == g.color(v))&lt;br /&gt;
            {		    &lt;br /&gt;
                queue.addElement(v);		    &lt;br /&gt;
                g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
        g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    for all vertices u at level d in parallel do&lt;br /&gt;
        for all adjacencies v of u in parallel do&lt;br /&gt;
        dv = D[v];&lt;br /&gt;
        if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
            vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
            if(vis == 0) // v is added to a stack only once&lt;br /&gt;
                D[v] = d+1;&lt;br /&gt;
                pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
        if(dv == d + 1)&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94792</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94792"/>
		<updated>2015-03-05T17:20:21Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Introduction to Linked-List Parallel Programming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
A [http://en.wikipedia.org/wiki/Linked_list linked lists] is a data structure which contains a set of nodes. Nodes in linked list are composed of data and references to next node. It is the simplest form of linked data structures. Other linked data structures include Trees, Hash Tables and Graphs. One component that tends to link together various linked data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine the paths.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With [http://en.wikipedia.org/wiki/Linked_list linked lists], there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
        parallel begin&lt;br /&gt;
            Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
            Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
        parallel end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
    Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
        parbegin&lt;br /&gt;
            Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
            Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
            /* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
            hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
            /* Phase 2. Build partial lists */&lt;br /&gt;
            Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
        parend;&lt;br /&gt;
    Step 2. Link up partial lists.&lt;br /&gt;
        /* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
        P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
        /* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
        for each of the p blocks do&lt;br /&gt;
            for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
            parbegin&lt;br /&gt;
                for i := 1 to (n/p^2) do&lt;br /&gt;
                begin&lt;br /&gt;
                    Pi is given at most a node mi in each iteration.&lt;br /&gt;
                    if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
                    then&lt;br /&gt;
                        if the global list for the level of node mi is empty&lt;br /&gt;
                        then&lt;br /&gt;
                            let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
                        else&lt;br /&gt;
                            list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
                        end;&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
                    if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 4. Obtain ranking&lt;br /&gt;
        LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
    Step 5. Output the result&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
            parend;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
    g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
    g.mark(false);          // unmark the whole graph&lt;br /&gt;
    refresh(null);          // and redraw it&lt;br /&gt;
    Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
    g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
    java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
    queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
    while(!queue.isEmpty())&lt;br /&gt;
    {&lt;br /&gt;
        Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
        queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
        g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
        int dp = g.degreePlus(u);&lt;br /&gt;
        for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
        {&lt;br /&gt;
            Vertex v = g.ithSucc(i, u);&lt;br /&gt;
            if(Color.white == g.color(v))&lt;br /&gt;
            {		    &lt;br /&gt;
                queue.addElement(v);		    &lt;br /&gt;
                g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
        g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    for all vertices u at level d in parallel do&lt;br /&gt;
        for all adjacencies v of u in parallel do&lt;br /&gt;
        dv = D[v];&lt;br /&gt;
        if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
            vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
            if(vis == 0) // v is added to a stack only once&lt;br /&gt;
                D[v] = d+1;&lt;br /&gt;
                pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
        if(dv == d + 1)&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94791</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94791"/>
		<updated>2015-03-05T17:16:40Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Introduction to Linked-List Parallel Programming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With [http://en.wikipedia.org/wiki/Linked_list linked lists], there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
        parallel begin&lt;br /&gt;
            Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
            Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
        parallel end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
    Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
        parbegin&lt;br /&gt;
            Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
            Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
            /* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
            hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
            /* Phase 2. Build partial lists */&lt;br /&gt;
            Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
        parend;&lt;br /&gt;
    Step 2. Link up partial lists.&lt;br /&gt;
        /* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
        P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
        /* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
        for each of the p blocks do&lt;br /&gt;
            for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
            parbegin&lt;br /&gt;
                for i := 1 to (n/p^2) do&lt;br /&gt;
                begin&lt;br /&gt;
                    Pi is given at most a node mi in each iteration.&lt;br /&gt;
                    if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
                    then&lt;br /&gt;
                        if the global list for the level of node mi is empty&lt;br /&gt;
                        then&lt;br /&gt;
                            let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
                        else&lt;br /&gt;
                            list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
                        end;&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
                    if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 4. Obtain ranking&lt;br /&gt;
        LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
    Step 5. Output the result&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
            parend;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
    g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
    g.mark(false);          // unmark the whole graph&lt;br /&gt;
    refresh(null);          // and redraw it&lt;br /&gt;
    Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
    g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
    java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
    queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
    while(!queue.isEmpty())&lt;br /&gt;
    {&lt;br /&gt;
        Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
        queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
        g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
        int dp = g.degreePlus(u);&lt;br /&gt;
        for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
        {&lt;br /&gt;
            Vertex v = g.ithSucc(i, u);&lt;br /&gt;
            if(Color.white == g.color(v))&lt;br /&gt;
            {		    &lt;br /&gt;
                queue.addElement(v);		    &lt;br /&gt;
                g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
        g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    for all vertices u at level d in parallel do&lt;br /&gt;
        for all adjacencies v of u in parallel do&lt;br /&gt;
        dv = D[v];&lt;br /&gt;
        if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
            vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
            if(vis == 0) // v is added to a stack only once&lt;br /&gt;
                D[v] = d+1;&lt;br /&gt;
                pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
        if(dv == d + 1)&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94790</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94790"/>
		<updated>2015-03-05T17:07:47Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
        parallel begin&lt;br /&gt;
            Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
            Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
        parallel end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
    Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
        parbegin&lt;br /&gt;
            Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
            Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
            /* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
            hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
            /* Phase 2. Build partial lists */&lt;br /&gt;
            Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
        parend;&lt;br /&gt;
    Step 2. Link up partial lists.&lt;br /&gt;
        /* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
        P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
        /* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
        for each of the p blocks do&lt;br /&gt;
            for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
            parbegin&lt;br /&gt;
                for i := 1 to (n/p^2) do&lt;br /&gt;
                begin&lt;br /&gt;
                    Pi is given at most a node mi in each iteration.&lt;br /&gt;
                    if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
                    then&lt;br /&gt;
                        if the global list for the level of node mi is empty&lt;br /&gt;
                        then&lt;br /&gt;
                            let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
                        else&lt;br /&gt;
                            list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
                        end;&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
                    if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 4. Obtain ranking&lt;br /&gt;
        LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
    Step 5. Output the result&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
            parend;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
    g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
    g.mark(false);          // unmark the whole graph&lt;br /&gt;
    refresh(null);          // and redraw it&lt;br /&gt;
    Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
    g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
    java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
    queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
    while(!queue.isEmpty())&lt;br /&gt;
    {&lt;br /&gt;
        Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
        queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
        g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
        int dp = g.degreePlus(u);&lt;br /&gt;
        for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
        {&lt;br /&gt;
            Vertex v = g.ithSucc(i, u);&lt;br /&gt;
            if(Color.white == g.color(v))&lt;br /&gt;
            {		    &lt;br /&gt;
                queue.addElement(v);		    &lt;br /&gt;
                g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
        g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    for all vertices u at level d in parallel do&lt;br /&gt;
        for all adjacencies v of u in parallel do&lt;br /&gt;
        dv = D[v];&lt;br /&gt;
        if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
            vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
            if(vis == 0) // v is added to a stack only once&lt;br /&gt;
                D[v] = d+1;&lt;br /&gt;
                pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
        if(dv == d + 1)&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94789</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94789"/>
		<updated>2015-03-05T16:55:29Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
        parallel begin&lt;br /&gt;
            Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
            Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
        parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
    Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
    for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
        parbegin&lt;br /&gt;
            Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
            Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
            /* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
            hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
            /* Phase 2. Build partial lists */&lt;br /&gt;
            Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
        parend;&lt;br /&gt;
    Step 2. Link up partial lists.&lt;br /&gt;
        /* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
        P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
        /* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
        for each of the p blocks do&lt;br /&gt;
            for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
            parbegin&lt;br /&gt;
                for i := 1 to (n/p^2) do&lt;br /&gt;
                begin&lt;br /&gt;
                    Pi is given at most a node mi in each iteration.&lt;br /&gt;
                    if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
                    then&lt;br /&gt;
                        if the global list for the level of node mi is empty&lt;br /&gt;
                        then&lt;br /&gt;
                            let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
                        else&lt;br /&gt;
                            list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
                        end;&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
                    if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
            parend;&lt;br /&gt;
    Step 4. Obtain ranking&lt;br /&gt;
        LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
    Step 5. Output the result&lt;br /&gt;
        for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
            parbegin&lt;br /&gt;
                for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
            parend;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
    g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
    g.mark(false);          // unmark the whole graph&lt;br /&gt;
    refresh(null);          // and redraw it&lt;br /&gt;
    Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
    g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
    java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
    queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
    while(!queue.isEmpty())&lt;br /&gt;
    {&lt;br /&gt;
        Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
        queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
        g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
        int dp = g.degreePlus(u);&lt;br /&gt;
        for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
        {&lt;br /&gt;
            Vertex v = g.ithSucc(i, u);&lt;br /&gt;
            if(Color.white == g.color(v))&lt;br /&gt;
            {		    &lt;br /&gt;
                queue.addElement(v);		    &lt;br /&gt;
                g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
        g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    for all vertices u at level d in parallel do&lt;br /&gt;
        for all adjacencies v of u in parallel do&lt;br /&gt;
        dv = D[v];&lt;br /&gt;
        if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
            vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
            if(vis == 0) // v is added to a stack only once&lt;br /&gt;
                D[v] = d+1;&lt;br /&gt;
                pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
        if(dv == d + 1)&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94788</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94788"/>
		<updated>2015-03-05T16:51:23Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
    g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
    g.mark(false);          // unmark the whole graph&lt;br /&gt;
    refresh(null);          // and redraw it&lt;br /&gt;
    Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
    g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
    java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
    queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
    while(!queue.isEmpty())&lt;br /&gt;
    {&lt;br /&gt;
        Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
        queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
        g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
        int dp = g.degreePlus(u);&lt;br /&gt;
        for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
        {&lt;br /&gt;
            Vertex v = g.ithSucc(i, u);&lt;br /&gt;
            if(Color.white == g.color(v))&lt;br /&gt;
            {		    &lt;br /&gt;
                queue.addElement(v);		    &lt;br /&gt;
                g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
        g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    for all vertices u at level d in parallel do&lt;br /&gt;
        for all adjacencies v of u in parallel do&lt;br /&gt;
        dv = D[v];&lt;br /&gt;
        if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
            vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
            if(vis == 0) // v is added to a stack only once&lt;br /&gt;
                D[v] = d+1;&lt;br /&gt;
                pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
        if(dv == d + 1)&lt;br /&gt;
            fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
            fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94787</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94787"/>
		<updated>2015-03-05T16:50:14Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Serial Code Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
    g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
    g.mark(false);          // unmark the whole graph&lt;br /&gt;
    refresh(null);          // and redraw it&lt;br /&gt;
    Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
    g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
    java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
    queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
    while(!queue.isEmpty())&lt;br /&gt;
    {&lt;br /&gt;
        Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
        queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
        g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
        int dp = g.degreePlus(u);&lt;br /&gt;
        for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
        {&lt;br /&gt;
            Vertex v = g.ithSucc(i, u);&lt;br /&gt;
            if(Color.white == g.color(v))&lt;br /&gt;
            {		    &lt;br /&gt;
                queue.addElement(v);		    &lt;br /&gt;
                g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
        g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94786</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94786"/>
		<updated>2015-03-05T16:48:30Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = new ConcurrentHashMap();&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
while (i.hasNext())&lt;br /&gt;
    foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94785</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94785"/>
		<updated>2015-03-05T16:47:59Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
    Integer oldVal, newVal;&lt;br /&gt;
    do {&lt;br /&gt;
        oldVal = queryCounts.get(q);&lt;br /&gt;
        newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
    } while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    Map m = new ConcurrentHashMap();&lt;br /&gt;
    Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94784</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94784"/>
		<updated>2015-03-05T16:47:19Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Serial Code Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
    Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
    while (i.hasNext())&lt;br /&gt;
        foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94783</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94783"/>
		<updated>2015-03-05T16:46:58Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Serial Code Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94782</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94782"/>
		<updated>2015-03-05T16:45:45Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
Integer cnt = queryCounts.get(q);&lt;br /&gt;
    if (cnt == null) {&lt;br /&gt;
        queryCounts.put(q, 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        queryCounts.put(q, cnt + 1);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94781</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94781"/>
		<updated>2015-03-05T16:43:34Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Serial Code Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94780</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94780"/>
		<updated>2015-03-05T16:42:15Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Hash Tables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Parallel-code.PNG&amp;diff=94779</id>
		<title>File:Parallel-code.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Parallel-code.PNG&amp;diff=94779"/>
		<updated>2015-03-05T16:40:16Z</updated>

		<summary type="html">&lt;p&gt;Vareti: uploaded a new version of &amp;amp;quot;File:Parallel-code.PNG&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94778</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94778"/>
		<updated>2015-03-05T16:33:40Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap&amp;lt;ref&amp;gt;http://code.wikia.com/wiki/Hashmap&amp;lt;/ref&amp;gt; class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;, which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]]&amp;lt;ref&amp;gt;http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]]&amp;lt;ref&amp;gt;http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94777</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94777"/>
		<updated>2015-03-05T16:29:59Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png|thumb|upright|]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94776</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94776"/>
		<updated>2015-03-05T16:14:29Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfect balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfect balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-tree labelled Rank 0, Rank 1, Rank 2 and Rank 3 is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94775</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94775"/>
		<updated>2015-03-05T16:10:10Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. Tree is a good candidate to exploit parallelism.  Since each node/sub-tree is independent in a binary tree, a large tree can be split up into 2, 4, 8, or more subtrees and each processor holds a sub-tree.  In this method, the only data that is common to all processors are the parent nodes of all sub-trees.  Consider a perfectly balanced binary tree which has k levels. So the total number of nodes in the tree will be equal to 2^k-1. An example of perfectly balanced binary tree is shown in the figure below. For the example shown below, four processors are required if each sub-trees colored in green is assigned to a single processor. The three nodes colored in red is the common data shared by all processors.So in this scenario, four processors each have four independent sub-trees and they share three nodes. In general, if n processors each have n independent sub-trees, they share n-1 nodes in common. If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94774</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94774"/>
		<updated>2015-03-05T15:26:21Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Parallel Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94773</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94773"/>
		<updated>2015-03-05T14:48:11Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94772</id>
		<title>CSC/ECE 506 Spring 2015/5a ss</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94772"/>
		<updated>2015-03-05T14:42:47Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]]&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
&amp;lt;ref&amp;gt;http://www.shodor.org/media/content//petascale/materials/UPModules/Binary_Tree_Traversal/Binary_Tree_Traversal_Module_Document.pdf&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables&amp;lt;ref&amp;gt;http://www.devjavasoft.org/code/classhashtable.html&amp;lt;/ref&amp;gt; are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''&amp;lt;ref&amp;gt;http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&amp;lt;/ref&amp;gt; consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users&amp;lt;ref&amp;gt;http://www.facebook.com/press/info.php?statistics&amp;lt;/ref&amp;gt; and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Breadth-first_search&amp;lt;/ref&amp;gt; as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]]&amp;lt;ref&amp;gt;http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.&amp;lt;ref&amp;gt;http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94771</id>
		<title>CSC/ECE 506 Spring 2015/5a ss</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94771"/>
		<updated>2015-03-05T14:30:51Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
='''References'''=&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94770</id>
		<title>CSC/ECE 506 Spring 2015/5a ss</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94770"/>
		<updated>2015-03-05T14:27:41Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
=='''References'''==&lt;br /&gt;
&amp;lt;div id=&amp;quot;referencesAnchor&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94769</id>
		<title>CSC/ECE 506 Spring 2015/5a ss</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_ss&amp;diff=94769"/>
		<updated>2015-03-05T14:26:37Z</updated>

		<summary type="html">&lt;p&gt;Vareti: Created page with &amp;quot;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =  Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm  Topic Write-up: htt...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
To understand how parallelization techniques are applied to linked data structures, a copy-scan technique is illustrated in brief, which is further extended to a partial sum computation in a linked list. &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below is an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree (this will be discussed in detail in the later section).  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sought of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94764</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94764"/>
		<updated>2015-03-03T07:51:59Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Pointer_jumping&amp;lt;/ref&amp;gt; aren't just for single linked lists. This algorithm can also be used to find the root of a tree, which will be discussed more in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below diagram shows an example which illustrates the algorithm discussed.&amp;lt;ref&amp;gt;Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore parallelization opportunities for hash tables, trees, and graph linked data structures.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure &amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_%28data_structure&amp;lt;/ref&amp;gt; contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithms&amp;lt;ref&amp;gt;http://en.wikipedia.org/wiki/Tree_traversal&amp;lt;/ref&amp;gt; using the tree shown below.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
Now that we have seen standard tree traversal techniques, we will look at how tree traversal can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&lt;br /&gt;
*http://en.wikipedia.org/wiki/Pointer_jumping&lt;br /&gt;
*http://en.wikipedia.org/wiki/Tree_%28data_structure%29&lt;br /&gt;
*http://oreilly.com/catalog/masteralgoc/chapter/ch08.pdf&lt;br /&gt;
*http://www.devjavasoft.org/code/classhashtable.html&lt;br /&gt;
*http://osr600doc.sco.com/en/SDK_c++/_Intro_graph.html&lt;br /&gt;
*http://web.eecs.utk.edu/~berry/cs302s02/src/code/Chap14/Graph.java&lt;br /&gt;
*http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&lt;br /&gt;
*http://rosettacode.org/wiki/Talk:Tree_traversal&lt;br /&gt;
*http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&lt;br /&gt;
*http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&lt;br /&gt;
*http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&lt;br /&gt;
*http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&lt;br /&gt;
*http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&lt;br /&gt;
*http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&lt;br /&gt;
*http://www.facebook.com/press/info.php?statistics&lt;br /&gt;
*http://en.wikipedia.org/wiki/Breadth-first_search&lt;br /&gt;
*http://code.wikia.com/wiki/Hashmap&lt;br /&gt;
*http://www.shodor.org/petascale/materials/UPModules/Binary_Tree_Traversal&lt;br /&gt;
*http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock&lt;br /&gt;
*http://dl.acm.org/citation.cfm?id=320078&lt;br /&gt;
*http://en.wikipedia.org/wiki/Tree_traversal&lt;br /&gt;
*P.-A. Larson, M. R. Krishnan,and G. V. Reilly, “Scaleable hash table for shared-memory multiprocessor system,” US Patent number: 6578131, 2003 http://ww2.cs.mu.oz.au/~pjs/papers/paralleldp.pdf&lt;br /&gt;
*Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&lt;br /&gt;
*http://en.wikipedia.org/wiki/Pointer_jumping&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94763</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94763"/>
		<updated>2015-03-03T06:43:04Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
*http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&lt;br /&gt;
*http://en.wikipedia.org/wiki/Pointer_jumping&lt;br /&gt;
*http://en.wikipedia.org/wiki/Tree_%28data_structure%29&lt;br /&gt;
*http://oreilly.com/catalog/masteralgoc/chapter/ch08.pdf&lt;br /&gt;
*http://www.devjavasoft.org/code/classhashtable.html&lt;br /&gt;
*http://osr600doc.sco.com/en/SDK_c++/_Intro_graph.html&lt;br /&gt;
*http://web.eecs.utk.edu/~berry/cs302s02/src/code/Chap14/Graph.java&lt;br /&gt;
*http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&lt;br /&gt;
*http://rosettacode.org/wiki/Talk:Tree_traversal&lt;br /&gt;
*http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&lt;br /&gt;
*http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&lt;br /&gt;
*http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&lt;br /&gt;
*http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&lt;br /&gt;
*http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&lt;br /&gt;
*http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&lt;br /&gt;
*http://www.facebook.com/press/info.php?statistics&lt;br /&gt;
*http://en.wikipedia.org/wiki/Breadth-first_search&lt;br /&gt;
*http://code.wikia.com/wiki/Hashmap&lt;br /&gt;
*http://www.shodor.org/petascale/materials/UPModules/Binary_Tree_Traversal&lt;br /&gt;
*http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock&lt;br /&gt;
*http://dl.acm.org/citation.cfm?id=320078&lt;br /&gt;
*http://en.wikipedia.org/wiki/Tree_traversal&lt;br /&gt;
*P.-A. Larson, M. R. Krishnan,and G. V. Reilly, “Scaleable hash table for shared-memory multiprocessor system,” US Patent number: 6578131, 2003 http://ww2.cs.mu.oz.au/~pjs/papers/paralleldp.pdf&lt;br /&gt;
*Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&lt;br /&gt;
*http://en.wikipedia.org/wiki/Pointer_jumping&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94762</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94762"/>
		<updated>2015-03-03T06:42:22Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
{{Refbegin}}&lt;br /&gt;
*http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&lt;br /&gt;
*http://en.wikipedia.org/wiki/Pointer_jumping&lt;br /&gt;
*http://en.wikipedia.org/wiki/Tree_%28data_structure%29&lt;br /&gt;
*http://oreilly.com/catalog/masteralgoc/chapter/ch08.pdf&lt;br /&gt;
*http://www.devjavasoft.org/code/classhashtable.html&lt;br /&gt;
*http://osr600doc.sco.com/en/SDK_c++/_Intro_graph.html&lt;br /&gt;
*http://web.eecs.utk.edu/~berry/cs302s02/src/code/Chap14/Graph.java&lt;br /&gt;
*http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&lt;br /&gt;
*http://rosettacode.org/wiki/Talk:Tree_traversal&lt;br /&gt;
*http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&lt;br /&gt;
*http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&lt;br /&gt;
*http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&lt;br /&gt;
*http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&lt;br /&gt;
*http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&lt;br /&gt;
*http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&lt;br /&gt;
*http://www.facebook.com/press/info.php?statistics&lt;br /&gt;
*http://en.wikipedia.org/wiki/Breadth-first_search&lt;br /&gt;
*http://code.wikia.com/wiki/Hashmap&lt;br /&gt;
*http://www.shodor.org/petascale/materials/UPModules/Binary_Tree_Traversal&lt;br /&gt;
*http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock&lt;br /&gt;
*http://dl.acm.org/citation.cfm?id=320078&lt;br /&gt;
*http://en.wikipedia.org/wiki/Tree_traversal&lt;br /&gt;
*P.-A. Larson, M. R. Krishnan,and G. V. Reilly, “Scaleable hash table for shared-memory multiprocessor system,” US Patent number: 6578131, 2003 http://ww2.cs.mu.oz.au/~pjs/papers/paralleldp.pdf&lt;br /&gt;
*Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&lt;br /&gt;
*http://en.wikipedia.org/wiki/Pointer_jumping&lt;br /&gt;
{{Refend}}&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94761</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94761"/>
		<updated>2015-03-03T06:38:24Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94760</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94760"/>
		<updated>2015-03-03T06:37:49Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
{{Reflist}}&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94759</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94759"/>
		<updated>2015-03-03T06:37:28Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
{{Reflist}}&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94758</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94758"/>
		<updated>2015-03-03T06:37:02Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
{{Reflist}}&lt;br /&gt;
#http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&lt;br /&gt;
#http://en.wikipedia.org/wiki/Pointer_jumping&lt;br /&gt;
#http://en.wikipedia.org/wiki/Tree_%28data_structure%29&lt;br /&gt;
#http://oreilly.com/catalog/masteralgoc/chapter/ch08.pdf&lt;br /&gt;
#http://www.devjavasoft.org/code/classhashtable.html&lt;br /&gt;
#http://osr600doc.sco.com/en/SDK_c++/_Intro_graph.html&lt;br /&gt;
#http://web.eecs.utk.edu/~berry/cs302s02/src/code/Chap14/Graph.java&lt;br /&gt;
#http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&lt;br /&gt;
#http://rosettacode.org/wiki/Talk:Tree_traversal&lt;br /&gt;
#http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&lt;br /&gt;
#http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&lt;br /&gt;
#http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&lt;br /&gt;
#http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&lt;br /&gt;
#http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&lt;br /&gt;
#http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&lt;br /&gt;
#http://www.facebook.com/press/info.php?statistics&lt;br /&gt;
#http://en.wikipedia.org/wiki/Breadth-first_search&lt;br /&gt;
#http://code.wikia.com/wiki/Hashmap&lt;br /&gt;
#http://www.shodor.org/petascale/materials/UPModules/Binary_Tree_Traversal&lt;br /&gt;
#http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock&lt;br /&gt;
#http://dl.acm.org/citation.cfm?id=320078&lt;br /&gt;
#http://en.wikipedia.org/wiki/Tree_traversal&lt;br /&gt;
#P.-A. Larson, M. R. Krishnan,and G. V. Reilly, “Scaleable hash table for shared-memory multiprocessor system,” US Patent number: 6578131, 2003 http://ww2.cs.mu.oz.au/~pjs/papers/paralleldp.pdf&lt;br /&gt;
#Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&lt;br /&gt;
#http://en.wikipedia.org/wiki/Pointer_jumping&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94757</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94757"/>
		<updated>2015-03-03T06:31:37Z</updated>

		<summary type="html">&lt;p&gt;Vareti: /* Introduction to Linked-List Parallel Programming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:&amp;lt;ref&amp;gt;http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
&lt;br /&gt;
#http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&lt;br /&gt;
#http://en.wikipedia.org/wiki/Pointer_jumping&lt;br /&gt;
#http://en.wikipedia.org/wiki/Tree_%28data_structure%29&lt;br /&gt;
#http://oreilly.com/catalog/masteralgoc/chapter/ch08.pdf&lt;br /&gt;
#http://www.devjavasoft.org/code/classhashtable.html&lt;br /&gt;
#http://osr600doc.sco.com/en/SDK_c++/_Intro_graph.html&lt;br /&gt;
#http://web.eecs.utk.edu/~berry/cs302s02/src/code/Chap14/Graph.java&lt;br /&gt;
#http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&lt;br /&gt;
#http://rosettacode.org/wiki/Talk:Tree_traversal&lt;br /&gt;
#http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&lt;br /&gt;
#http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&lt;br /&gt;
#http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&lt;br /&gt;
#http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&lt;br /&gt;
#http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&lt;br /&gt;
#http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&lt;br /&gt;
#http://www.facebook.com/press/info.php?statistics&lt;br /&gt;
#http://en.wikipedia.org/wiki/Breadth-first_search&lt;br /&gt;
#http://code.wikia.com/wiki/Hashmap&lt;br /&gt;
#http://www.shodor.org/petascale/materials/UPModules/Binary_Tree_Traversal&lt;br /&gt;
#http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock&lt;br /&gt;
#http://dl.acm.org/citation.cfm?id=320078&lt;br /&gt;
#http://en.wikipedia.org/wiki/Tree_traversal&lt;br /&gt;
#P.-A. Larson, M. R. Krishnan,and G. V. Reilly, “Scaleable hash table for shared-memory multiprocessor system,” US Patent number: 6578131, 2003 http://ww2.cs.mu.oz.au/~pjs/papers/paralleldp.pdf&lt;br /&gt;
#Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&lt;br /&gt;
#http://en.wikipedia.org/wiki/Pointer_jumping&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94756</id>
		<title>CSC/ECE 506 Spring 2015/5a vv</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_506_Spring_2015/5a_vv&amp;diff=94756"/>
		<updated>2015-03-03T05:38:48Z</updated>

		<summary type="html">&lt;p&gt;Vareti: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Chapter 5a CSC/ECE 506 Spring 2015 / Other linked data structures =&lt;br /&gt;
&lt;br /&gt;
Original wiki : http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_506_Spring_2014/5a_rm&lt;br /&gt;
&lt;br /&gt;
Topic Write-up: http://courses.ncsu.edu/csc506/lec/001/homework/ch5_6.html&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
Linked Data Structures (LDS) consists of different types of data structures such as [http://en.wikipedia.org/wiki/Linked_list linked lists], [http://en.wikibooks.org/wiki/Data_Structures/Trees trees], [http://en.wikipedia.org/wiki/Hash_table hash tables] and [http://en.wikibooks.org/wiki/Data_Structures/Graphs graphs]. Although each structure is diversed, LDS traversal shares a common characteristic in reading a node and discovering the other nodes it points to. Hence, this often introduces loop carried dependence. Chapter 5 of Solihin, discusses various algorithms on parallelizing LDS using a simple linked list. In this wiki, we attempt to cover other LDS such as trees, hashes and graphs, and see how the parallelization algorithms discussed can be applied to these structures.&lt;br /&gt;
&lt;br /&gt;
= Introduction to Linked-List Parallel Programming =&lt;br /&gt;
&lt;br /&gt;
One component that tends to link together various data structures is their dependence at some level on an internal pointer-based linked list.  For example, hash tables have linked lists to support chained links to a given bucket in order to resolve collisions, trees have linked lists with left and right tree node paths, and graphs have linked lists to determine shortest path algorithms.&lt;br /&gt;
&lt;br /&gt;
But what mechanism allows us to generate parallel algorithms for these structures?  &lt;br /&gt;
&lt;br /&gt;
For an array processing algorithm, a common technique used at the processor level is the copy-scan technique.  This technique involves copying rows of data from one processor to another in a log(n) fashion until all processors have their own copy of that row.  From there, you could perform a reduction technique to generate a sum of all the data, all while working in a parallel fashion.  Take the following grid:[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The basic process for copy-scan would be to:&lt;br /&gt;
# In the first step, copy the row 1 elements to corresponding index numbers of row 2 array.&lt;br /&gt;
# In second step, copy the row 1 elements to corresponding indexes in array of row 3, similarly row 2 elements -&amp;gt; row 4.&lt;br /&gt;
# In this manner, in the nth step, 2^n rows can copied to 2^n rows &lt;br /&gt;
# This can operation is performed until all rows have been copied in a log(n) fashion.&lt;br /&gt;
# Perform the parallel operations to generate the desired result (reduction for sum, etc.).&lt;br /&gt;
&lt;br /&gt;
[[File:CopyScan.gif]]&lt;br /&gt;
&lt;br /&gt;
But how does this same process work in the linked list world?&lt;br /&gt;
&lt;br /&gt;
With linked lists, there is a concept called pointer doubling, which works in a very similar manner to copy-scan.[[#References|&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
# Each processor will make a copy of the pointer it holds to its neighbor.&lt;br /&gt;
# Next, each processor will make a pointer to the processor 2 steps away.&lt;br /&gt;
# This continues in logarithmic fashion until each processor has a pointer to the end of the chain.&lt;br /&gt;
# Perform the parallel operations to generate the desired result.&lt;br /&gt;
&lt;br /&gt;
Pointer doubling or [https://en.wikipedia.org/wiki/Pointer_jumping pointer jumping] can be used for performing partial sums of a linked list. This is accomplished by adding the value held by the node with the value stored in the node it is pointing to. This is repeated until all pointers have reached the end of the list. The result is a linked list which contains the sum of the node and all preceding nodes. Below shows an example of this algorithm in action.&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums1.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums2.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums3.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:PartialSums4.png]]&lt;br /&gt;
&lt;br /&gt;
The advantages of Pointer jumping[[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] aren't just for single linked lists. This algorithm can also be used for finding the roots of trees, which we will talk more about in the next section.  The way in which this algorithm is used, is similar to the previous example.  Each node will point to the next node until it reaches the end.  The result is that every node will have a pointer to the root of the tree.  Below is an example of this process.[[#References|&amp;lt;sup&amp;gt;[24]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
[[File:Pointer_Jumping_Example.png]]&lt;br /&gt;
&lt;br /&gt;
However, with linked list programming, similar to array-based programming, it becomes imperative to have some sort of locking mechanism or other parallel technique for [http://en.wikipedia.org/wiki/Critical_section critical sections] in order to avoid [http://en.wikipedia.org/wiki/Race_condition race conditions].  To make sure the results are correct, it is important that operations can be serialized appropriately and that data remains current and synchronized.&lt;br /&gt;
&lt;br /&gt;
In this chapter, we will explore 3 linked-list based data structures and the parallelization opportunities: hash tables, trees, and graphs.&lt;br /&gt;
&lt;br /&gt;
== Trees ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Trees ===&lt;br /&gt;
&lt;br /&gt;
A tree data structure [[#References|&amp;lt;sup&amp;gt;[2]&amp;lt;/sup&amp;gt;]] contains a set of ordered nodes with one parent node followed by zero or more child nodes.  Typically this tree structure is used with searching or sorting algorithms to achieve log(n) efficiencies.  Assuming you have a balanced tree, or a relatively equal set of nodes under each branching structure of the tree, and assuming a proper ordering structure, searches/inserts/deletes should occur far more quickly than having to traverse an entire list.&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
One potential slowdown in a tree data structure could occur during the traversal process.  Even though search/update/insert can occur in a logarithmic fashion, traversal operations such as in-order, pre-order, post-order traversals can still require a full sequence of the list to generate all output.  This gives an opportunity to generate parallel code by having various portions of the traversal occur on different processors.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Example ===&lt;br /&gt;
&lt;br /&gt;
In this section, we will begin by showing different serial tree traversal algorithm using the tree shown below.[[#References|&amp;lt;sup&amp;gt;[8]&amp;lt;/sup&amp;gt;]] The four ordering algorithms that we will cover are pre-order, in-order, post-order, and level order.  &lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
          1&lt;br /&gt;
         / \&lt;br /&gt;
        /   \&lt;br /&gt;
       /     \&lt;br /&gt;
      2       3&lt;br /&gt;
     / \     /&lt;br /&gt;
    4   5   6&lt;br /&gt;
   /       / \&lt;br /&gt;
  7       8   9&lt;br /&gt;
&lt;br /&gt;
The correct output should look like this:&lt;br /&gt;
 preorder:    1 2 4 7 5 3 6 8 9&lt;br /&gt;
 inorder:     7 4 2 5 1 8 6 9 3&lt;br /&gt;
 postorder:   7 4 5 2 8 9 6 3 1&lt;br /&gt;
 level-order: 1 2 3 4 5 6 7 8 9&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Traversal ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Tree_Traversal is&lt;br /&gt;
&lt;br /&gt;
  '''type''' ''Node''; &lt;br /&gt;
  '''type''' Node_Access is access Node;&lt;br /&gt;
  '''type''' Node is record&lt;br /&gt;
     Left  : Node_Access := null;&lt;br /&gt;
     Right : Node_Access := null;&lt;br /&gt;
     Data  : Integer;&lt;br /&gt;
  end record;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Tree Destroy ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Destroy_Tree(N : in out Node_Access) is&lt;br /&gt;
&lt;br /&gt;
   procedure free is new Ada.Unchecked_Deallocation(Node, Node_Access);&lt;br /&gt;
     begin&lt;br /&gt;
       if N.Left /= null then&lt;br /&gt;
          Destroy_Tree(N.Left);&lt;br /&gt;
       end if;&lt;br /&gt;
       if N.Right /= null then &lt;br /&gt;
          Destroy_Tree(N.Right);&lt;br /&gt;
       end if;&lt;br /&gt;
       Free(N);&lt;br /&gt;
   end Destroy_Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Node Access ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Function Tree(Value : Integer; Left : Node_Access; Right : Node_Access) return Node_Access is&lt;br /&gt;
  Temp : Node_Access := new Node;&lt;br /&gt;
 begin&lt;br /&gt;
  Temp.Data := Value;&lt;br /&gt;
  Temp.Left := Left;&lt;br /&gt;
  Temp.Right := Right;&lt;br /&gt;
  return Temp;&lt;br /&gt;
 end Tree;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Preorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Preorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Preorder(N.Left); &lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Preorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
 end Preorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Inorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Inorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
   if N.Left /= null then&lt;br /&gt;
      Inorder(N.Left);&lt;br /&gt;
   end if;&lt;br /&gt;
   Put(Integer'Image(N.Data));&lt;br /&gt;
   if N.Right /= null then&lt;br /&gt;
      Inorder(N.Right);&lt;br /&gt;
   end if;&lt;br /&gt;
 end Inorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Postorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Postorder(N : Node_Access) is&lt;br /&gt;
 begin&lt;br /&gt;
  if N.Left /= null then&lt;br /&gt;
     Postorder(N.Left);&lt;br /&gt;
  end if;&lt;br /&gt;
  if N.Right /= null then&lt;br /&gt;
     Postorder(N.Right);&lt;br /&gt;
  end if;&lt;br /&gt;
  Put(Integer'Image(N.Data));&lt;br /&gt;
 end Postorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Levelorder ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
Procedure Levelorder(N : Node_Access) is&lt;br /&gt;
  Package Queues is new Ada.Containers.Doubly_Linked_Lists(Node_Access);&lt;br /&gt;
  use Queues;&lt;br /&gt;
  Node_Queue : List;&lt;br /&gt;
  Next : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
  Node_Queue.Append(N);&lt;br /&gt;
  while not Is_Empty(Node_Queue) loop&lt;br /&gt;
     Next := First_Element(Node_Queue);&lt;br /&gt;
     Delete_First(Node_Queue);&lt;br /&gt;
     Put(Integer'Image(Next.Data));&lt;br /&gt;
     if Next.Left /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Left);&lt;br /&gt;
     end if;&lt;br /&gt;
     if Next.Right /= null then&lt;br /&gt;
        Node_Queue.Append(Next.Right);&lt;br /&gt;
     end if;&lt;br /&gt;
  end loop;&lt;br /&gt;
 end Levelorder;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== main  ====&lt;br /&gt;
{|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
 N : Node_Access;&lt;br /&gt;
 begin&lt;br /&gt;
    N := Tree(1,&lt;br /&gt;
                Tree(2,&lt;br /&gt;
                       Tree(4,&lt;br /&gt;
                              Tree(7, null, null),&lt;br /&gt;
                              null),&lt;br /&gt;
                       Tree(5, null, null)),&lt;br /&gt;
                Tree(3,&lt;br /&gt;
                       Tree(6,&lt;br /&gt;
                              Tree(8, null, null),&lt;br /&gt;
                              Tree(9, null, null)),&lt;br /&gt;
                       null));&lt;br /&gt;
 &lt;br /&gt;
  Put(&amp;quot;preorder:    &amp;quot;);&lt;br /&gt;
  Preorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;inorder:     &amp;quot;);&lt;br /&gt;
  Inorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;postorder:   &amp;quot;);&lt;br /&gt;
  Postorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Put(&amp;quot;level order: &amp;quot;);&lt;br /&gt;
  Levelorder(N);&lt;br /&gt;
  New_Line;&lt;br /&gt;
  Destroy_Tree(N);&lt;br /&gt;
 end Tree_traversal;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
Now that we have seen what a standard parallel tree traversal is, we will look at how trees can be parallelized. In many ways, a tree is the perfect candidate for parallelism.  In a tree, each node/subtree is independent.  As a result, we can split up a large tree into 2, 4, 8, or &lt;br /&gt;
more subtrees and hold subtree on each processor.  Then, the only duplicated data that must be kept on all processors is the parent node to all the subtrees.  Mathematically speaking, for a tree divided among 'n' processors (where n is a power of two), the processors only need to hold 'n – 1' nodes &lt;br /&gt;
in common – no matter how big the tree itself is. This is shown in the figure below.  Since we are using 4 processors, we will only need 3 nodes in common.  This is because one node is capable of having two branches.  If the size of the tree was increased and the number of processors was also increased, the number of shared nodes would also increase to support the increased number of sub-trees.[[#References|&amp;lt;sup&amp;gt;[21]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The fact that trees are comprised of independent sub-trees makes parallelizing them very easy.  Properly done, the portion of these traversals that is parallelizable grows at 2n for an n-generation tree. While the processors only need to synchronize once, at the end, the parallelizable portion approaches 100% for large trees (but keep in mind [http://en.wikipedia.org/wiki/Amdahl's_law Amdahl’s Law], footnote 1).  The basic steps for parallelizing these traversals are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the appropriate C algorithm detailed above.&lt;br /&gt;
# The processor will return its result that can be used exactly as if it was a serial processor.&lt;br /&gt;
&lt;br /&gt;
[[File:parallel_tree.png]][[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
A [http://www.cs.bu.edu/teaching/c/tree/breadth-first/ Breadth-First traversal] is somewhat more complicated to implement as a parallel system because at each level, it must access nodes from all of the parallel processors.  Theoretically, a Breadth-First traversal can achieve complete parallelization of Pre-, In-, and Post-Order traversals.  As the degree of parallelism is increased, the speed up increases as per Amdahl's law. One thing to remember in the parllelization though, is that the amount of processor-to-processor data transmission adds in a greater potential for delays, thus slowing &lt;br /&gt;
down the algorithm.  Nevertheless, as the size of the tree increases the size of the generations grows at the rate of 2n while the number of synchronizations grows at a rate of n for an n-generation tree, so the parallelizable portion of these traversals also approaches 100%.  The basic steps for parallelizing this traversal are as follows:&lt;br /&gt;
&lt;br /&gt;
# Perform the traversal on the parent part of the tree.&lt;br /&gt;
# Whenever you get to a node that is only present on one processor, ask that processor to execute the Breadth-First C algorithm detailed above, but wait after it finishes one generation.&lt;br /&gt;
# Combine all the one-generation results from the different processors in the correct order.&lt;br /&gt;
# Allow each processor to execute the next generation of the Breadth-First C algorithm detailed above, and then wait again.&lt;br /&gt;
# Repeat Steps 3 and 4 until there are no nodes remaining&lt;br /&gt;
[[#References|&amp;lt;sup&amp;gt;[18]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Here, since each processor is assigned an independent sub-tree, elaborate locks are not required.&lt;br /&gt;
&lt;br /&gt;
An example of a parallel Breadth-First tree traversal is shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:ExampleTree.png]] &lt;br /&gt;
&lt;br /&gt;
The data structure can be constructed from the input tree using the GEN-COMP-NEXT algorithm. The result is a linked list from the input tree which is represented as a &amp;quot;parent-of&amp;quot; relation with explicit ordering of children.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm GEN-COMP-NEXT:&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=n, do&lt;br /&gt;
::parallel begin&lt;br /&gt;
:::Step 1: Processor Pi builds the jth field of i's parent node if i is the jth child of its parent. The jth field (if it is not the last field) is stored in the ith index of array SUPERNODE.&lt;br /&gt;
:::Step 2: Processor Pi builds node i's last fiend whose array index is (n+1)&lt;br /&gt;
::parallel end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is the algorithm to perform a Breadth-First tree traversal in parallel where bfrank is the output parameter, array[1..n] of integer; level is the input parameter, array[1..n] of integer; and preorder list is an input parameter, array[1..n] of integer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Algorithm BF-TRAVERSAL (bfank, level, preorder-list)&lt;br /&gt;
:Step 1. Divide the preorder-list into p blocks. Each processor builds partial lists from the nodes in the block. The header and the taller arrays for the lists built by processor i are denoted by hd[*,i] and tl[*,i], respectively.&lt;br /&gt;
:for all Pi, 1&amp;lt;=i&amp;lt;=p do&lt;br /&gt;
::parbegin&lt;br /&gt;
:::Pi works on nodes pre-order-list[k], where (i-1)*(n/p) &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
:::Pi initializes list[k] to zreo /* the successor of k-th input in a partial list */&lt;br /&gt;
:::/* Phase 1. Pi initializes entries in hd[*,i] and tl[*,i] that are used and entries in hdflag */&lt;br /&gt;
:::hd[level[preorder-list[k]], i] := 0; tl[level[preorder-list[k]], i] := 0; hdflag[k] := 0;&lt;br /&gt;
:::/* Phase 2. Build partial lists */&lt;br /&gt;
:::Pi adds each of the n/p nodes to the partial list for the level of that node and updates hd[*,i], tl[*, i], and list [*] accordingly.&lt;br /&gt;
::parend;&lt;br /&gt;
:Step 2. Link up partial lists.&lt;br /&gt;
::/* Phase 1. Initialize header and tailer for the global lists */&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::initialize head[k] and tail[k] to zero, for (i-1)*n/p &amp;lt;= k &amp;lt; (i*n/p)&lt;br /&gt;
::P1 sets head[n+1] and tail[n+1] to zero;&lt;br /&gt;
::/* Phase 2. Link partial lists to form a list for each level */&lt;br /&gt;
::for each of the p blocks do&lt;br /&gt;
:::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do /* all processors work on the same block */&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for i := 1 to (n/p^2) do&lt;br /&gt;
::::begin&lt;br /&gt;
:::::Pi is given at most a node mi in each iteration.&lt;br /&gt;
:::::if hdflag[mi] = 1 /* The first element in its partial list */&lt;br /&gt;
:::::then&lt;br /&gt;
::::::if the global list for the level of node mi is empty&lt;br /&gt;
::::::then let head[level[mi]] and tail[level[mi]] point to mi&lt;br /&gt;
::::::else list[tail[level[mi]]] := mi and update tail[level[mi]] to be the tail of the partial list for mi.&lt;br /&gt;
::::::end;&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 3. Create a linked list to implement the NEXT function&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do&lt;br /&gt;
:::::if(head[k] != 0 and head[k+1] != 0) then list[tail[k]] := head[k+1];&lt;br /&gt;
:::parend;&lt;br /&gt;
:Step 4. Obtain ranking&lt;br /&gt;
::LINKED-LIST-RANKING(list, tmp-rank, n);&lt;br /&gt;
:Step 5. Output the result&lt;br /&gt;
::for all Pi, 1 &amp;lt;= i &amp;lt;= p, do&lt;br /&gt;
:::parbegin&lt;br /&gt;
::::for k := (i-1)*(n/p)+1 to (i*n/p) do bfrank[preorder-list[k]] := tmp-rank[k];&lt;br /&gt;
:::parend;&lt;br /&gt;
&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To obtain the required tree-traversals, the following rules are operated on the linked list produced by algorithm GEN-COMP-NEXT:&lt;br /&gt;
* pre-order traversal: select the first copy of each node;&lt;br /&gt;
* post-order traversal: select the last copy of each node;&lt;br /&gt;
* in-order traversal: delete the first copy of each node if it is not a leaf and delete the last copy of each node if it has more than one child.&lt;br /&gt;
&lt;br /&gt;
Since the tree is transformed into a linked list by the GEN-COMP-NEXT function, it can be locked while editing as per the LDS chapter in Solihin book. Either a Global lock approach, Fine Grained approach or [http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock Read-Write Locks] can be used.  Since the tree is able to be transformed into a simple linked list, we are able to use the same locking mechanism for multiple linked data structure types.&lt;br /&gt;
In this fashion we have broken up the linked list of the tree into successive parts and imposed a divide-and-conquer technique to complete the traversal.&lt;br /&gt;
&lt;br /&gt;
== Hash Tables ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Hash Tables ===&lt;br /&gt;
&lt;br /&gt;
Hash tables[[#References|&amp;lt;sup&amp;gt;[4]&amp;lt;/sup&amp;gt;]] are very efficient data structures often used in searching algorithms for fast lookup operations. They are used extensively in data processing as in involves a vast amount of data through the hash table using as few indirection's in the storage structure as possible.   &lt;br /&gt;
&lt;br /&gt;
A single hash table level look can easily become a bottleneck, thus several method were developed to overcome this difficulty. Hash tables contain a series of &amp;quot;buckets&amp;quot; that function like indexes into an array, each of which can be accessed directly using their key value.  The bucket for which a piece of data will be placed is determine by a special hashing function.&lt;br /&gt;
&lt;br /&gt;
The major advantage of a hash table is that lookup times are essentially a constant value, much like an array with a known index.  With a proper hashing function in place, it should be fairly rare that any 2 keys would generate the same value.&lt;br /&gt;
&lt;br /&gt;
In the case that 2 keys do map to the same position, there is a conflict that must be dealt with in some fashion to obtain the correct value.  One way that is relevant to linked list structures is to have a chained hash table in which a linked list is created with all values that have been placed in that particular bucket.  The developer would have to not only take into account the proper bucket for the data being searched for, but also must considered the chained linked list. [[#References|&amp;lt;sup&amp;gt;[7]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
There are several parallel implementations of hash tables available that use lock-based synchronization. Larson et al. use two lock levels, there is one global table level lock, and there is one separate lightweight lock (a flag) for each bucket. The high level lock is just used for setting the bucket level flags and released right afterwards. This ensures a fine grained mutual exclusion (concurrent operations on bucket level), but needs only one real lock for the implementation. &lt;br /&gt;
&lt;br /&gt;
A scalable hash table for shared memory multi-processor (SMP) supports very high rates of concurrent operations (e.g., insert, delete, &lt;br /&gt;
and lookup), while simultaneously reducing cache misses. The SMP system has a memory subsystem and a processor subsystem interconnected &lt;br /&gt;
via a bus structure. &lt;br /&gt;
&lt;br /&gt;
The hash table is stored in the memory subsystem to facilitate access to data items. The hash table is segmented into multiple buckets, &lt;br /&gt;
with each bucket containing a reference to a linked list of bucket nodes that hold references to data items with keys that hash to a common value. Individual bucket nodes contain multiple signature-pointer pairs that reference corresponding data items.&lt;br /&gt;
Each signature-pointer pair has a hash signature computed from a key of the data item and a pointer to the data item. The first bucket &lt;br /&gt;
node in the linked list for each of the buckets is stored in the hash table.&lt;br /&gt;
&lt;br /&gt;
To enable multithread access, while serializing operation of the table, the SMP system utilizes two levels of locks: a table lock and&lt;br /&gt;
multiple bucket locks. The table lock allows access by a single processing thread to the table while blocking access for other processing&lt;br /&gt;
threads. The table lock is held just long enough for the thread to acquire the bucket lock of a particular bucket node. Once the table lock&lt;br /&gt;
is released, another thread can access the hash table and any one of the other buckets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:315px-Hash table 3 1 1 0 1 0 0 SP.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Hash tables can be very well suited to parallel applications.  For example, system code responsible for caching between multiple processors could itself be an ideal opportunity for a shared hashmap.  Each processor sharing one common cache would be able to access the relevant information all in one location.&lt;br /&gt;
&lt;br /&gt;
This would, however, involve a good bit of synchronization, as each processor would need to wait in case a lock was being placed on a specific bucket in the cache hashmap.  Unfortunately, traditional locking would be a bad solution to this problem as processors need to run very quickly.  Having to wait for locks would destroy the application processing time.  The need for a non-locking solution is critical to performance.&lt;br /&gt;
&lt;br /&gt;
In Java, the standard class utilized for hashing is the HashMap[[#References|&amp;lt;sup&amp;gt;[17]&amp;lt;/sup&amp;gt;]] class.  This class has a fundamental weakness though in that the entire map requires synchronization prior to each access.  This causes a lot of contention and many bottlenecks on a parallel machine.&lt;br /&gt;
&lt;br /&gt;
Below, I will present a Java-based solution to this problem by using a ConcurrentHashMap class.  This class only requires a portion of the map to be locked and reads can generally occur with no locking whatsoever.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
'''  Simple synchronized example to increment a counter.'''[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private Map&amp;lt;String,Integer&amp;gt; queryCounts = new HashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private '''synchronized''' void incrementCount(String q) {&lt;br /&gt;
:Integer cnt = queryCounts.get(q);&lt;br /&gt;
:if (cnt == null) {&lt;br /&gt;
::queryCounts.put(q, 1);&lt;br /&gt;
:} else {&lt;br /&gt;
::queryCounts.put(q, cnt + 1);&lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code was written using an ordinary HashMap data structure.  Notice that we use the synchronized keyword here to signify that only one thread can enter this function at any one point in time.  With a really large number of threads, however, waiting to enter the synchronized operation could be a major bottleneck.&lt;br /&gt;
&lt;br /&gt;
'''  Iterator example for synchronized HashMap.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Map m = Collections.synchronizedMap(new HashMap());&amp;lt;br&amp;gt;&lt;br /&gt;
Set s = m.keySet(); // set of keys in hashmap&amp;lt;br&amp;gt;&lt;br /&gt;
synchronized(m) { // synchronizing on map&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above example, we show how an iterator could be used to traverse over a map.  In this case, we would need to utilize the synchronizedMap function available in the Collections interface.  Also, as you may notice, once the iterator code begins we must actually synchronize on the entire map in order to iterate through the results.  But what if several processors wish to iterate through at the same time?&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
The key issue in a hash table in a parallel environment is to make sure any update/insert/delete sequences have been completed properly prior to attempting subsequent operations to make sure the data has been synched appropriately.  However, since access speed is such a critical component of the design of a hash table, it is essential to try and avoid using too many locks for performing synchronization.  Fortunately, a number of lock-free hash designs have been implemented to avoid this bottleneck.&lt;br /&gt;
&lt;br /&gt;
One such example in Java is the ConcurrentHashMap[[#References|&amp;lt;sup&amp;gt;[9]&amp;lt;/sup&amp;gt;]], which acts as a synchronized version of the [http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html HashMap].  With this structure, there is full concurrency of retrievals and adjustable expected concurrency for updates.  There is, however, no locking in this data structure and retrievals will typically run in parallel along with updates/deletes.  Retrievals, however, will receive all most recently completed transactions even if it cannot get the values that haven't finished being updated.  This both allows for efficiency and greater concurrency.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Counter Increment Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
private ConcurrentMap&amp;lt;String,Integer&amp;gt; queryCounts = new ConcurrentHashMap&amp;lt;String,Integer&amp;gt;(1000);&amp;lt;br&amp;gt;&lt;br /&gt;
private void incrementCount(String q) {&lt;br /&gt;
:Integer oldVal, newVal;&lt;br /&gt;
:do {&lt;br /&gt;
::oldVal = queryCounts.get(q);&lt;br /&gt;
::newVal = (oldVal == null) ? 1 : (oldVal + 1);&lt;br /&gt;
:} while (!queryCounts.replace(q, oldVal, newVal));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code snippet represents an alternative to the serial option presented in the previous section, while also avoiding much of the locking that takes place using the synchronized functions or synchronized blocks.  With ConcurrentHashMap, however, notice that we must implement some new code in order to handle the fact that a variety of inserts/updates could be running at the same time.  The replace() function here acts much like a compare-and-set operation typically used with concurrent code.  Basically, the value would be changed only if not equal to the previously mapped value.  This is much more efficient that locking the entire function as we often do not expect unequal values.&lt;br /&gt;
&lt;br /&gt;
'''Parallel Traversal Alternative:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:Map m = new ConcurrentHashMap();&lt;br /&gt;
:Set s = m.keySet(); // set of keys in hashmap&lt;br /&gt;
:Iterator i = s.iterator(); // Must be in synchronized block&lt;br /&gt;
:while (i.hasNext())&lt;br /&gt;
::foo(i.next());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the case of a traversal, recall that ConcurrentHashMaps require to locking on read operations.  Thus we can actually remove the synchronized condition here and iterate in a normal fashion.&lt;br /&gt;
&lt;br /&gt;
== Graphs ==&lt;br /&gt;
&lt;br /&gt;
=== Introduction to Graph Data Structure ===&lt;br /&gt;
&lt;br /&gt;
A graph data structure[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] is another type of linked-list structure that focuses on data relationships and the most efficient ways to traverse from one node to another.  For example, in a networking application, one network node may have connections to a variety of other network nodes.  These nodes then also link to a variety of other nodes in the network.  Using this connection of nodes, it would be possible to then find a path from one specific node to another in the chain.  This could be accomplished by having each node contain a linked list of pointers to all other reachable nodes.&lt;br /&gt;
&lt;br /&gt;
[[File:250px-6n-graf.svg.png]]&lt;br /&gt;
&lt;br /&gt;
=== Opportunities for Parallelization ===&lt;br /&gt;
&lt;br /&gt;
Graphs[[#References|&amp;lt;sup&amp;gt;[10]&amp;lt;/sup&amp;gt;]] consist of a finite set of ordered pairs called edges or arcs, of certain entities called nodes or vertices.  From one given vertex, one would typically want to order the different paths from one vertex to another using its list of edges or, more than likely, would be interested in the fastest means of getting from one of these vertexes to some sort of destination vertex.&lt;br /&gt;
&lt;br /&gt;
Graph nodes typically will keep their list of edges in a linked list.  Also, when attempting to create a shortest path algorithm on the fly, the graph will typically use a combination of a linked list to represent the path as it's being built, along with a queue that is used for each step of that process.  Synchronizing all of these can be a major challenge.&lt;br /&gt;
&lt;br /&gt;
Much like the hash table, graphs cannot afford to be slow and must often generate results in a very efficient manner.  Having to lock on each list of edges or locking on a shortest path list would really be a major obstacle.&lt;br /&gt;
&lt;br /&gt;
Certainly though, the need for parallel processing becomes critical when you consider, for example, that social networking has become such a major proponent of graph algorithms.  Facebook now has roughly a billion users[[#References|&amp;lt;sup&amp;gt;[15]&amp;lt;/sup&amp;gt;]] and each user has series of friend links that must be analyzed and examined.  This list just keeps growing and growing.&lt;br /&gt;
&lt;br /&gt;
One of the most significant opportunities for a parallel algorithm with a graph data structure is with the traversal algorithms.  We can use Breadth-First search[[#References|&amp;lt;sup&amp;gt;[16]&amp;lt;/sup&amp;gt;]] as an example of this, starting from an initial node and expanding outwards until reaching the destination node.&lt;br /&gt;
&lt;br /&gt;
=== Serial Code Examples ===&lt;br /&gt;
&lt;br /&gt;
''' Bread First Search '''&lt;br /&gt;
&lt;br /&gt;
The following shows a sample of a bread first algorithm which traverses from the city of Frankfurt to Augsburg and Stuttgart Germany.  In does so, the graph begins at a root node (Frankfurt) and expands outwardly to all connected nodes on each step.  From there, each of those nodes proceeds to expand the search outwards until all nodes have been covered.&lt;br /&gt;
&lt;br /&gt;
[[File:GermanyBFS.png]][[#References|&amp;lt;sup&amp;gt;[13]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following code snippet implements a BFS search function.  This function utilized coloring schemes and marks to denote that a node has been visited.  It begins with an initial vertex in a queue and expands outward to all its successors until no further elements remain unmarked.[[#References|&amp;lt;sup&amp;gt;[12]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public void search(Graph g)&lt;br /&gt;
{&lt;br /&gt;
:g.paint(Color.white);   // paint all the graph vertices with white&lt;br /&gt;
:g.mark(false);          // unmark the whole graph&lt;br /&gt;
:refresh(null);          // and redraw it&lt;br /&gt;
:Vertex r = g.root();    // the root is painted grey&lt;br /&gt;
:g.paint(r, Color.gray);       refresh(g.box(r));&lt;br /&gt;
:java.util.Vector queue = new java.util.Vector();	&lt;br /&gt;
:queue.addElement(r);    // and put in a queue&lt;br /&gt;
&lt;br /&gt;
:while(!queue.isEmpty())&lt;br /&gt;
:{&lt;br /&gt;
::Vertex u = (Vertex) queue.firstElement();&lt;br /&gt;
::queue.removeElement(u); // extract a vertex from the queue&lt;br /&gt;
::g.mark(u, true);          refresh(g.box(u));&lt;br /&gt;
::int dp = g.degreePlus(u);&lt;br /&gt;
::for(int i = 0; i &amp;lt; dp; i++) // look at its successors&lt;br /&gt;
::{&lt;br /&gt;
:::Vertex v = g.ithSucc(i, u);&lt;br /&gt;
:::if(Color.white == g.color(v))&lt;br /&gt;
:::{		    &lt;br /&gt;
::::queue.addElement(v);		    &lt;br /&gt;
::::g.paint(v, Color.gray);   refresh(g.box(v));&lt;br /&gt;
:::}&lt;br /&gt;
::}&lt;br /&gt;
::g.paint(u, Color.black);  refresh(g.box(u));&lt;br /&gt;
::g.mark(u, false);         refresh(g.box(u));	    &lt;br /&gt;
:}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Parallel Solution ===&lt;br /&gt;
&lt;br /&gt;
But could we introduce parallel mechanisms into this Breadth First search?  The most logical and effective way, instead of utilizing locks and synchronized regions, is to use data parallel techniques during the traversal.  This can be accomplished by having each node of a given breadth search step be sent to a separate processor.  So, using the above example, instead of having Frankfurt-&amp;gt;Mannheim followed by Frankfurt-&amp;gt;Wurzburg followed by Frankfurt-&amp;gt;Bassel on the same processor, Frankfurt could split out all 3 searches in a parallel fashion onto 3 different processors.  Then, possible some cleanup code would be left at the end to visit any remaining untouched nodes.  In a network routing applications, being able to split up the search for each IP address code would make searched significantly faster that allowing one processor to be a bottleneck.&lt;br /&gt;
&lt;br /&gt;
Using locking pseudocode, you might have an algorithm similar to this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
:for all vertices u at level d in parallel do&lt;br /&gt;
::for all adjacencies v of u in parallel do&lt;br /&gt;
::dv = D[v];&lt;br /&gt;
::if(dv &amp;lt; 0) // v is visited for the first time&lt;br /&gt;
:::vis = fetch_and_add(&amp;amp;Visited[v], 1);  '''LOCK'''&lt;br /&gt;
:::if(vis == 0) // v is added to a stack only once&lt;br /&gt;
::::D[v] = d+1;&lt;br /&gt;
::::pS[count++] = v; // Add v to local thread stack&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
::if(dv == d + 1)&lt;br /&gt;
:::fetch_and_add(&amp;amp;sigma[v], sigma[u]);  '''LOCK'''&lt;br /&gt;
:::fetch_and_add(&amp;amp;Pcount[v], 1); // Add u to predecessor list of v  '''LOCK'''&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A much better parallel algorithm is represented in the following pseudocode.  Notice that each of the vertices is sent to a separate processor and send/receive operations will eventually sync up the path information.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-code.PNG]][[#References|&amp;lt;sup&amp;gt;[14]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
The following graph also shows how now each of the regional sets of vertices being search can be added to the path in a parallel fashion.&lt;br /&gt;
&lt;br /&gt;
[[File:Parallel-graph.PNG]][[#References|&amp;lt;sup&amp;gt;[11]&amp;lt;/sup&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Every set of vertices in the same distance from the source is assigned to a processor. This set of vertices is called a regional set of vertices. The goal is to find the shortest path connecting each region.&lt;br /&gt;
&lt;br /&gt;
As shown, maps are able to be parallelized using very similar traversal methods seen in trees.  We have also highlighted the importance of graphs and their need to be accessed quickly.  Due to this need for access speed, graphs benefit greatly from parallelization.&lt;br /&gt;
&lt;br /&gt;
= Conclusion =&lt;br /&gt;
Through this wiki page we have shown how parallelization can be done for trees, hash tables, and graphs.  While the structures are more complex than the single linked lists outlined in the Solihin textbook, their parallelization methods pull heavily from the fundamental locking techniques taught there.  In several cases, the exact same locking techniques are used and it is the LDS which is manipulated to create single linked lists.  In this way we are able to show how these basic principals taught by the text book are able to be expanded and carried into more complex structures and problems.&lt;br /&gt;
&lt;br /&gt;
= Quiz =&lt;br /&gt;
&lt;br /&gt;
1. Describe the copy-scan technique.&lt;br /&gt;
&lt;br /&gt;
2. Describe the pointer doubling technique.&lt;br /&gt;
&lt;br /&gt;
3. Which concurrency issues are of the most concern in a tree data structure?&lt;br /&gt;
&lt;br /&gt;
4. What is the alternative to using a copy-scan technique in pointer-based programming?&lt;br /&gt;
&lt;br /&gt;
5. Which concurrency issues are of the most concern with hash table data structures?&lt;br /&gt;
&lt;br /&gt;
6. Which concurrency issues are of the most concern with graph data structures?&lt;br /&gt;
&lt;br /&gt;
7. Why would you not want locking mechanisms in hash tables?&lt;br /&gt;
&lt;br /&gt;
8. What is the nature of the linked list in a tree structure?&lt;br /&gt;
&lt;br /&gt;
9. Describe a parallel alternative in the tree data structure.&lt;br /&gt;
&lt;br /&gt;
10. Describe a parallel alternative in a graph data structure.&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
&lt;br /&gt;
#http://people.engr.ncsu.edu/efg/506/s01/lectures/notes/lec8.html&lt;br /&gt;
#http://en.wikipedia.org/wiki/Pointer_jumping&lt;br /&gt;
#http://en.wikipedia.org/wiki/Tree_%28data_structure%29&lt;br /&gt;
#http://oreilly.com/catalog/masteralgoc/chapter/ch08.pdf&lt;br /&gt;
#http://www.devjavasoft.org/code/classhashtable.html&lt;br /&gt;
#http://osr600doc.sco.com/en/SDK_c++/_Intro_graph.html&lt;br /&gt;
#http://web.eecs.utk.edu/~berry/cs302s02/src/code/Chap14/Graph.java&lt;br /&gt;
#http://en.wikipedia.org/wiki/File:Hash_table_3_1_1_0_1_0_0_SP.svg&lt;br /&gt;
#http://rosettacode.org/wiki/Talk:Tree_traversal&lt;br /&gt;
#http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap.shtml&lt;br /&gt;
#http://en.wikipedia.org/wiki/Graph_%28abstract_data_type%29&lt;br /&gt;
#http://www.cc.gatech.edu/~bader/papers/PPoPP12/PPoPP-2012-part2.pdf&lt;br /&gt;
#http://renaud.waldura.com/portfolio/graph-algorithms/classes/graph/BFSearch.java&lt;br /&gt;
#http://en.wikipedia.org/w/index.php?title=File%3AGermanyBFS.svg&lt;br /&gt;
#http://sc05.supercomputing.org/schedule/pdf/pap346.pdf&lt;br /&gt;
#http://www.facebook.com/press/info.php?statistics&lt;br /&gt;
#http://en.wikipedia.org/wiki/Breadth-first_search&lt;br /&gt;
#http://code.wikia.com/wiki/Hashmap&lt;br /&gt;
#http://www.shodor.org/petascale/materials/UPModules/Binary_Tree_Traversal&lt;br /&gt;
#http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock&lt;br /&gt;
#http://dl.acm.org/citation.cfm?id=320078&lt;br /&gt;
#http://en.wikipedia.org/wiki/Tree_traversal&lt;br /&gt;
#P.-A. Larson, M. R. Krishnan,and G. V. Reilly, “Scaleable hash table for shared-memory multiprocessor system,” US Patent number: 6578131, 2003 http://ww2.cs.mu.oz.au/~pjs/papers/paralleldp.pdf&lt;br /&gt;
#Calvin C.-Y.Chen, Sajal K. Das, &amp;quot;Parallel Breadth-first and Breadth-depth traversals of general trees&amp;quot;, Advances in Computing and Information - ICCP '90, ISBN: 978-3-540-46677-2&lt;br /&gt;
#http://en.wikipedia.org/wiki/Pointer_jumping&lt;/div&gt;</summary>
		<author><name>Vareti</name></author>
	</entry>
</feed>