Open main menu

CDOT Wiki β

GPU621/Go Parallel

Go (Language) Parallel Programming

Description

Our team wants to demonstrate the usefulness of the Go programming language while applying Parallel programming principles. Demonstrations of the difference in time, syntax, and ease of use will be included within the document. The topic of whether using a newly created language like Go compared to an older language like C++ will make a difference in terms of future popularity will also be a key point in our report. Success for this project means displaying the differences between the two languages and educating other students about the possibility to use different languages to do parallel programming

What is Go?

As explained in the Go official website "Go is an open source programming language that makes it easy to build simple, reliable, and efficient software"[1]. Created on a whiteboard in 2007 which later became open source in 2009. Go is the collaboration of many different programmers that were tired of the choices that they had to make between languages. Either they chose efficient compilation, efficient execution, or ease of programming; no mainstream languages had all three of these characteristics. Thus Go was created, a language that would combine all three of these characteristics into one. A main point brought up in Go's Creations was "It must be modern. C, C++, and to some extent Java are quite old, designed before the advent of multicore machines, networking, and web application development. There are features of the modern world that are better met by newer approaches, such as built-in concurrency"[2] which means that at its core, Go supports multicore parallel programming.

Installation

Installing Go is simple! Follow these simple steps or go to the official install documentation

1. Download Go

Find your operating system at https://golang.org/dl/ and download the Go Language





2. Install Go

Open the file and follow the prompts







3. You're done!

Go is now downloaded and installed on your machine, to test if the installation worked properly, go into your command prompt and enter 'go version'





Concurrency and Parallelism

Go was designed for concurrency. “Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.” [3] - Rob Pike (One of the programmers of Go). Concurrency is NOT parallel programming.

Quoting Sun's Multithreaded Programming Guide on the Oracle Documentation website -

Parallelism is defined as:

   Parallelism - A condition that arises when at least two threads are executing simultaneously.

While Concurrency is defined as:

   Concurrency - A condition that exists when at least two threads are making progress. A more generalized form of parallelism that can include time-slicing as a form of virtual parallelism.

But what about Go?

As stated above, Concurrency is NOT parallel programming. But working with both is very easy to do in Go.

A big thing to note about Go is the 'goroutines' which is what allow programmers to run functions or methods concurrently.

   go function_name(parameters)

Using the key term 'go' allows the program to run concurrently, BUT in order for your program to run in parallel you can use the key term 'GOMAXPROCS'

   func GOMAXPROCS(n int) int

'GOMAXPROCS' allows the programmer to specify the MAX amount of CPU's that will be executing code simultaneously. By default, GOMAXPROCS is set to the number of cores available.


If you're more interested in the differences between Concurrency and Parallelism we found a great explanation here: https://stackoverflow.com/a/24684037/8644993

Differences

Code Differences

Go Code for Monte Carlo Estimation of Pi

 
package main

import (
	"fmt"
	"math"
	"math/rand"
	"os"
	"runtime"
	"strconv"
	"sync"
	"time"
)

func monte_carlo_pi(radius float64, reps int, result *int, wait *sync.WaitGroup) {
	var x, y float64
	count := 0
	seed := rand.NewSource(time.Now().UnixNano()) // creates a seed using time
	random := rand.New(seed)                      // create a new random genrator using the seed

	for i := 0; i < reps; i++ { // for the number of reps we get a random number and multiple it by radius
		x = random.Float64() * radius
		y = random.Float64() * radius

		if num := math.Sqrt(x*x + y*y); num < radius { // checks to see if num is inside unit circle
			count++
		}
	}

	*result = count
	wait.Done()
}

func main() {
	cores := runtime.NumCPU() // grabs the numof cpu on runtime
	runtime.GOMAXPROCS(cores) // gets the number of thread set by the os

	var wait sync.WaitGroup

	counts := make([]int, cores) // creates an array depending on the number of cores

	samples, _ := strconv.Atoi(os.Args[1]) // gets the number of samples

	start := time.Now() // gets the starting time;
	wait.Add(cores)     // adds the amount of cores to wait for

	for i := 0; i < cores; i++ {
		go monte_carlo_pi(100.0, samples/cores, &counts[i], &wait) // uses goroutines to start threading interms of the runtime GOMAXPROCS
	}

	wait.Wait() // waits until all cores have finished

	total := 0
	for i := 0; i < cores; i++ {
		total += counts[i]
	}

	pi := (float64(total) / float64(samples)) * 4 // gets the value of pi

	fmt.Println("Time: ", time.Since(start))
	fmt.Println("pi: ", pi)
	fmt.Println("")
}

C++ openMP Code for Monte Carlo Estimation of Pi

/*
 * Compute pi by Monte Carlo calculation of area of a circle
 *
 * parallel version using OpenMP
 */
#include <iostream>
#include <cstdlib>
#include <chrono>
#include <omp.h>
using namespace std::chrono;
using namespace std;
void reportTime(const char *msg, steady_clock::duration span)
{
    auto ms = duration_cast<milliseconds>(span);
    std::cout << msg << " - took - " << ms.count() << " milliseconds" << std::endl;
}
int main(int argc, char *argv[])
{

    const char Usage[] = "Usage: pi <steps> <repeats> (try 1000000 4)";
    if (argc < 3)
    {
        cerr << Usage << endl;
        return (1);
    }
    int num_steps = atoi(argv[1]);
    int num_repeats = atoi(argv[2]);

    printf("Computing pi via Monte Carlo using %d steps, repeating %d times\n",
           num_steps, num_repeats);

// A little throwaway parallel section just to show num threads
#pragma omp parallel
#pragma omp master
    printf("Using %d threads\n", omp_get_num_threads());

    steady_clock::time_point ts, te;

    int count = 0;
    ts = steady_clock::now();
#pragma omp parallel for reduction(+ \
                                   : count) //redection of the count

    for (int i = 0; i < num_steps; i++)
    {
        double x = (double)rand() / RAND_MAX;
        double y = (double)rand() / RAND_MAX;
        if (x * x + y * y < 1) // checks if values are in the unit circle
            count++;
    }
    te = steady_clock::now();
    double pi = 4.0 * count / num_steps;
    printf("pi = %lf \n", pi);
    reportTime("pi", te - ts);
    printf("\n");
    return 0;
}

Time Differences

The time difference between the Go code and the C++ code gets significantly large as the sample size increases. The below table will show a the difference in time between the 2 source codes.


The difference between the two source codes
Sample Size C++ OMP Go Parallel Difference
100,000 8ms 0.7ms 11 times
1,000,000 79ms 1.9ms 42 times
10,000,000 1005ms 10ms 101 times
100,000,000 9757ms 105ms 92 times
1,000,000,000 97525ms 1094ms 89 times

Note : Go is using 1 CPU core with the max number of threads available on the OS. Where as C++ is using 8 threads. Go is using default compiler settings. C++ is using G++ at O3 optimization.


The difference is to large to be shown on a graph.

Ease of Use

Overall, the ease of use of Go is much simpler as Go has built-in support for concurrency and parallelism. While, C++ needs the assistance of external dependencies like open MP. The other thing Go uses CPU cores and then threads it on each core available with the max amount of threads available making the comparison sort of unfair as Go is automatically using the best configuration for the solution. While, In C++ with open MP you have to specify how many to use externally. Go is just much easier to use an implement a parallel/Concurrent solution than C++.

Relevance

Present and Future

Presently C++ is a language that is so intertwined with programming it would be hard for any language to surpass it in terms of relevance. Many systems/programs depend on C++ for core functionality and because the technology world moves/evolves so quickly it is hard for programmers to transfer systems over to a new language without encountering major issues.

But what do the people say?

But that doesn't mean that Go isn't used today, on Tiobes Programming Language Index [4] C++ is currently in fourth place, Go is 13th. The difference? C++ hasn't made any movement from 4th place for an entire year, while Go last year of November 2019 was at the 20th place, It has gone up 7 places in just 1 year.

Stack Overflow has also released their 2020 Developer Survey[5] and the results show that currently for the most loved languages, Go is in 5th place and C++ is 18th. In terms of popularity C++ is 10th place while Go is 12th.

And obviously major companies have already begun incorporating Go into their projects such as Google, YouTube, Uber, Intel, and Heroku.

What's the future like?

The future looks bright for Go and it's gaining traction quick. Since it's a language that was literally meant to be a replacement for these older languages like C++ it definitely has the edge when incorporating new technologies that are introduced because of hardware advancements (Such has multi-core CPU's).

Pros and Cons

Pros

1. Tons of support

2. Ease of use

3. Major companies use it

4. Better security integrations

Cons

1. Lack of versatility

2. Young language

3. Smaller Community


More about the pros and cons can be found at: https://www.geeksforgeeks.org/go-vs-c-plus-plus/

Why should you Go Parallel?

While currently C++ is generally a better language to learn parallel programming concepts from, and is also more used within the programming industry. Go is gaining popularity quickly and with the creation of Go meant to improve upon C++ weaknesses the future of Go is looking very good. Parallel programming in Go is extremely easy and has built in support for it (No need to go through any installation https://ict.senecacollege.ca/~gpu621/pages/content/suppo.html). In addition Go is a fun language to learn and could seriously be used over many of the other high-level programming languages.


A major thing to remember is that during Go's creation, multi-core CPU's were currently being made and popularized. This is very advantageous over C++ since in 1979 multi-core CPU's were unheard of and the first multi-core CPU was introduced in 2001.

Group Members

1. Michael Brackett

2. Devansh Shah

Progress

Update 1: Sunday, Nov 8, 2020 - Created description for project.

Update 2: Friday, Nov 13, 2020 - Created description for Go Language

Update 3: Sunday, Nov 15, 2020 - Created Installation Instructions

Update 4: Sunday, Nov 15, 2020 - Created Pros and Cons

Update 5: Tuesday, Nov 17, 2020 - Created 'Why you should Go Parallel'

Update 6: Thursday, Nov 19th, 2020 - Added Differences

Update 6: Thursday, Nov 19th, 2020 - Added all parts of project onto project website

Update 7: Thursday, Nov 19th, 2020 - Added Pictures to Installation Instructions

References