package main import ( "encoding/csv" "fmt" "io" "io/ioutil" "log" "math" "strconv" "strings" "time" ) var ( amountOfStars int ) func main() { var tests = []int64{ 1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000, } data := ReadData("data/200000.csv") for _, element := range tests { data = data[:element] var processedStars []Star var cores = 8 amountOfStars = len(data) processedChannel := make(chan Star, 1) var starsPerCore = amountOfStars / cores overallStartTime := time.Now() // start n threads processing stars for i := 0; i < cores; i++ { //fmt.Printf("Core %d processing #%d-#%d\n", i, i*starsPerCore, (i*starsPerCore)+(starsPerCore-1)) var begin = i * starsPerCore var end = (i * starsPerCore) + (starsPerCore) go ProcessStar(data, begin, end, processedChannel) } processedChannel <- Star{} doneStartingThreads := time.Now() // get the results through the processedChannel for i := 0; i < amountOfStars+1; i++ { newStar := <-processedChannel processedStars = append(processedStars, newStar) } doneGettingResults := time.Now() threadStartTime := doneStartingThreads.Sub(overallStartTime) calculationTime := doneGettingResults.Sub(overallStartTime) fmt.Printf("--------------------------------------------------------------------------------\n") fmt.Printf("Amount of Stars: %d\n", amountOfStars) fmt.Printf("Amount of Calculations: %e\n", float64(amountOfStars*amountOfStars)) fmt.Printf("Amount of Threads: %d\n", cores) fmt.Printf("Amount of stars per thread: %d\n", starsPerCore) fmt.Printf("Thread start time: %f sec.\n", threadStartTime.Seconds()) fmt.Printf("Calculation time: %f sec.\n", calculationTime.Seconds()) fmt.Printf("Calculation time per star: %f sec.\n", calculationTime.Seconds()/float64(amountOfStars)) fmt.Printf("Calculation per second: %e\n", float64(amountOfStars*amountOfStars)/calculationTime.Seconds()) } } type Star struct { C, V Vec3 M float64 } type Vec3 struct { X, Y, Z float64 } func check(e error) { if e != nil { panic(e) } } func ReadData(filepath string) []Star { // open the .csv dat, err := ioutil.ReadFile(filepath) check(err) // create a new csv reader r := csv.NewReader(strings.NewReader(string(dat))) var arrayOfStars []Star for { record, err := r.Read() if err == io.EOF { break } if err != nil { log.Fatal(err) } // parse the values x, parseErr := strconv.ParseFloat(record[0], 64) y, parseErr := strconv.ParseFloat(record[0], 64) z, parseErr := strconv.ParseFloat(record[0], 64) check(parseErr) // define a star var localStar = Star{Vec3{x, y, z}, Vec3{0, 0, 0}, 2e30} // append the star to the list of stars arrayOfStars = append(arrayOfStars, localStar) } return arrayOfStars } // CalcForce calculates the force exerted on s1 by s2 and returns a vector representing that force func CalcForce(s1 Star, s2 Star) Vec3 { G := 6.6726 * math.Pow(10, -11) // calculate the force acting var combinedMass = s1.M * s2.M var distance = math.Sqrt(math.Pow(math.Abs(s1.C.X-s2.C.X), 2) + math.Pow(math.Abs(s1.C.Y-s2.C.Y), 2)) var scalar = G * ((combinedMass) / math.Pow(distance, 2)) // define a unit vector pointing from s1 to s2 var vector = Vec3{s2.C.X - s1.C.X, s2.C.Y - s1.C.Y, s2.C.Z - s1.C.Z} var UnitVector = Vec3{vector.X / distance, vector.Y / distance, vector.Z / distance} // multiply the vector with the force to get a vector representing the force acting var force = UnitVector.Multiply(scalar) // return the force exerted on s1 by s2 return force } // Multiply returns the product of the vector and a scalar s func (v *Vec3) Multiply(s float64) Vec3 { return Vec3{v.X * s, v.Y * s, v.Z * s} } func ProcessStar(data []Star, begin int, end int, returnChannel chan Star) { // iterate over the given range of data for i := begin; i < end; i++ { localStar := data[i] var Force Vec3 // iterate over all the other stars for index := range data { if index != i { // calculate the force acting on the star force := CalcForce(localStar, data[index]) // add the force onto the overall force Force.X += force.X Force.Y += force.Y Force.Z += force.Z } } newStar := Star{ C: Vec3{ X: data[i].C.X, Y: data[i].C.Y, Z: data[i].C.Z, }, V: Vec3{ X: Force.X / float64(amountOfStars), Y: Force.Y / float64(amountOfStars), Z: Force.Z / float64(amountOfStars), }, M: data[i].M, } returnChannel <- newStar } return }