Пример #1
0
// DotInt64 performs a dot product on two arrays of float64
func DotInt64(a, b []int64) int64 {
	result := int64(0)
	if a != nil && b != nil {
		length := gomath.MinInt(len(a), len(b))

		a = a[:length]
		b = b[:length]

		thunk := func() DotThunk {
			localResult := int64(0)
			return DotThunk{
				Save: func() {
					result += localResult
				},
				Dot: func(start, end int) {
					for start < end {
						localResult += a[start] * b[start]
						start++
					}
				},
				Print: func(i int) {
					log.Println(i, ": ", localResult)
				},
			}
		}
		generateAndRun(thunk, length)
	}
	return result
}
Пример #2
0
// DotFloat32 performs a dot product on two arrays of float32
func DotFloat32(a, b []float32) float32 {

	f, err := os.Create("profile.prof")
	if err != nil {
		log.Fatal(err)
	}
	pprof.StartCPUProfile(f)
	defer pprof.StopCPUProfile()

	result := float32(0.0)

	if a != nil && b != nil {
		length := gomath.MinInt(len(a), len(b))

		a = a[:length]
		b = b[:length]

		thunk := func() DotThunk {
			localResult := float32(0)
			return DotThunk{
				Save: func() {
					result += localResult
				},
				Dot: func(start, end int) {
					for start < end {
						localResult += a[start] * b[start]
						start++
					}
				},
				Print: func(i int) {
					log.Println(i, ": ", localResult)
				},
			}
		}
		generateAndRun(thunk, length)
	} else {
		panic(fmt.Sprint("Invalid parameters:", a, b))
	}
	return result
}
Пример #3
0
func init() {
	features := 8
	jump := 1000
	var wg sync.WaitGroup
	LargeData = make([]classify.Data, LargeK)
	for i := 0; i < LargeK; i += jump {
		wg.Add(1)
		go func(i int) {
			start := i
			end := gomath.MinInt(LargeK, i+jump)
			for start < end {
				vArray := make([]gotypes.Value, features)
				LargeData[start] = &mydata{value: vArray, class: 0}
				for k := range vArray {
					vArray[k] = gotypes.WrapReal(rand.Float64())
				}
				start++
			}
			wg.Done()
		}(i)
	}
	wg.Wait()
}
Пример #4
0
// Foreach mimics a parallel foreach construct
//
//      This code should be equivalent to the serial code:
//
//          for i := 0 ; i < iterations; i++ {
//              f(i);
//          }
//
//  @f          -   Function to call in each iteration of the for loop
//  @iterations -   How many iterations we should perform
//
//
//
func Foreach(f func(i int) bool, iterations int) {
	rt := GetRuntime()
	rt.Start()

	jobs := []Job(nil)

	for iter := 0; iter < iterations; iter += _BatchSize {

		function := func(start, end int) func(int) bool {
			return func(i int) bool {
				if i >= end {
					return false
				}
				return f(i)
			}
		}(iter, gomath.MinInt(iter+_BatchSize, iterations))

		theJob := CreateIterableJob("Foreach", function, iter)

		jobs = append(jobs, theJob)
	}
	Run(jobs)
}
Пример #5
0
func generateAndRun(thunkFunc func() DotThunk, length int) {
	_maxThreads := 16
	_minWork := parallels.MinWorkPerThread

	threads := (length + _minWork - 1) / _minWork
	if threads > _maxThreads {
		threads = _maxThreads
		_minWork = (length + threads - 1) / threads
	}

	var lock sync.Mutex
	theJobs := []parallels.Job(nil)

	for threadID := 0; threadID < threads; threadID++ {
		myFunc := func(threadID, start, end int, mutex *sync.Mutex) parallels.Job {
			f := generateFunction(thunkFunc(), start, end, mutex)
			return parallels.CreateIterableJob(fmt.Sprint("Dot Product ", threadID, end), f, 0)
		}
		start := threadID * _minWork
		end := gomath.MinInt(start+_minWork, length)
		theJobs = append(theJobs, myFunc(threadID, start, end, &lock))
	}
	parallels.Run(theJobs)
}
Пример #6
0
// KMeans clustering
// TODO: Change to not only be numeric
func KMeans(data []classify.Data, K int, metric Metric, means [][]float64) [][]float64 {

	features := len(data[0].Value())

	if means == nil {
		/* Todo: randomly initialize k means */
		means = make([][]float64, K)
		for i := range means {
			means[i] = make([]float64, features)
			val := data[rand.Intn(len(data))]
			for j, v := range val.Value() {
				means[i][j] = v.Real()
			}
		}
	}

	counts := make([]int, K)
	newMeans := make([][]float64, K)
	for i := range newMeans {
		newMeans[i] = make([]float64, features)
	}

	maxElemPerThread := 10000 // 1K
	iterations := gomath.MaxInt(1, (len(data)+maxElemPerThread-1)/maxElemPerThread)
	elemPerThread := (len(data) + iterations - 1) / iterations

	change := true
	for change {
		change = false
		var lock sync.Mutex
		parallels.Foreach(func(i int) bool {
			// List of stuff
			nMs := make([][]float64, K)
			cs := make([]int, K)

			for i := range nMs {
				nMs[i] = make([]float64, features)
			}

			start := i * elemPerThread
			end := gomath.MinInt(start+elemPerThread, len(data))

			for start < end {
				d := data[start]
				closest := 0
				wrap, err := gotypes.WrapArray(means[0], gotypes.Array)
				if err != nil {
					panic(err)
				}
				dist := metric(d.Value(), wrap.Array())
				for k := 1; k < K; k++ {
					wrap, err = gotypes.WrapArray(means[k], gotypes.Array)
					if err != nil {
						panic(err)
					}
					nDist := metric(d.Value(), wrap.Array())
					if nDist < dist {
						dist = nDist
						closest = k
					}
				}

				// Save
				cs[closest]++
				for i := 0; i < features; i++ {
					t := d.Value()[i].Real()
					nMs[closest][i] += t
				}

				start++
			}

			lock.Lock()
			defer lock.Unlock()

			for i := 0; i < K; i++ {
				for j := 0; j < features; j++ {
					newMeans[i][j] += nMs[i][j]
				}
				counts[i] += cs[i]
			}
			return false
		}, iterations)

		// Update means
		for i := range newMeans {
			for j := range newMeans[i] {
				newMeans[i][j] /= float64(counts[i])
			}
			if !same(newMeans[i], means[i]) {
				change = true
			}
			for j := range newMeans[i] {
				means[i][j] = newMeans[i][j]
				newMeans[i][j] = 0
			}
			counts[i] = 0
		}
	}

	return means
}