GPU621/Go Parallel
GPU621/DPS921 | Participants | Groups and Projects | Resources | Glossary
Contents
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.
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
https://software.intel.com/content/www/us/en/develop/blogs/go-parallel.html
https://talks.golang.org/2012/splash.article
https://golang.org/pkg/runtime/#GOMAXPROCS
https://docs.oracle.com/cd/E19455-01/806-5257/6je9h032b/index.html
https://stackoverflow.com/a/24684037/8644993
https://www.tiobe.com/tiobe-index/
https://brainhub.eu/blog/biggest-companies-using-golang/
https://insights.stackoverflow.com/survey/2020
https://github.com/golang/go/wiki/GoUsers
https://www.geeksforgeeks.org/go-vs-c-plus-plus/