I have nearly implemented a face recognition Go server. My face recognition algorithm uses caffe
, caffe
is a thread-binding graphical library, that means I have to init and call algorithm in same thread, so I checked LockOSThread().
LockOSThread
uses 1 thread, but my server owns 4 GPU.
In C/C++
, I could create 4 threads, initialize algorithm in each thread, use sem_wait
and sem_post
to assign task, 1 thread use 1 GPU.
How to do the same thing in Go
, how to bind code with thread?
You spawn some number of goroutines, run runtime.LockOSThread()
in each and then initialize your graphical library in each.
You then use regular Go communication primitives to send tasks to those goroutines. Usually, the most simple way is to have each goroutine read "tasks" from a channel and send the results back, like in
type Task struct {
Data DataTypeToContainRecognitionTask
Result chan<- DataTypeToContainRecognitionResult
}
func GoroutineLoop(tasks <-chan Task) {
for task := range tasks {
task.Result <- recognize(Data)
}
}
tasks := make(chan Task)
for n := 4; n > 0; n-- {
go GoroutineLoop(tasks)
}
for {
res := make(chan DataTypeToContainRecognitionResult)
tasks <- Task{
Data: makeRecognitionData(),
Result: res,
}
result <- res
// Do something with the result
}
As to figuring out how much goroutines to start, there exist different strategies. The simplest approach is probably to query runtime.NumCPU()
and using this number.