我有一个for循环的标准。我有一个8核处理器,16个线程。运行此循环时,我看到只有1个线程用于100%。 我希望示例可以由所有CPU内核处理一次循环,这可能吗? 我看到了goroutine,但是通常取决于上下文,即并行的独立任务。有人可以修复我的代码,使其使用所有CPU内核吗?
package main
import (
"fmt"
"net/http"
"runtime"
"time"
)
func main() {
fmt.Println(runtime.NumCPU())
fmt.Println("hi man!");
timestart := time.Now();
for i := int64(0); i < 9007199915; i++ {
if (testMy(i) == true) {
fmt.Println("was returned true")
}
}
timeend := time.Now();
fmt.Print(timeend.Sub(timestart));
}
func testMy(someInteger int64) (bool) {
if (someInteger == 5) {
return true;
} else if (someInteger == 900199) {
return true;
} else if (someInteger == 9001999) {
return true;
} else {
return false;
}
}
更新:在这种情况下,任何人都可以建议一种编程语言吗?也就是说,以我的FOR LOOP周期并在较低级别对其进行并行化。
答案 0 :(得分:2)
在 Go 中很简单,只需使用goroutines在CPU内核之间划分任务即可。
让我给你一个例子(见这个for k := 0; k < nCPU; k++ {...}
循环):
想象一下,您需要了解所有CPU内核中最大的64位素数(与您的问题类似,这里是一个for循环,我在CPU内核之间进行了划分:for i := start; i <= end && atomic.LoadInt32(&quit) == 0; i += 2 {...}
):
package main
import (
"fmt"
"math"
"runtime"
"sync"
"sync/atomic"
)
func main() {
// find max uint64 prime
n := uint64(math.MaxUint64)
for ; !isOddPrime(n); n -= 2 {
}
fmt.Println(n) // 18446744073709551557
}
var nCPU = runtime.NumCPU()
func isOddPrime(n uint64) bool {
q := uint64(math.Sqrt(float64(n)))
step := q / uint64(nCPU)
if step&1 == 1 {
step++ // make it even
}
var wg sync.WaitGroup
wg.Add(nCPU)
var quit int32
start := uint64(3)
for k := 0; k < nCPU; k++ {
end := start + step
if end > q {
end = q
}
go func(start, end uint64) {
defer wg.Done()
for i := start; i <= end && atomic.LoadInt32(&quit) == 0; i += 2 {
if n%i == 0 {
atomic.StoreInt32(&quit, 1)
return
}
}
}(start, end)
start = end + 2
}
wg.Wait()
return quit == 0
}
具有8个内核的输出:
18446744073709551557
real 0m5.551s
user 0m39.059s
sys 0m0.040s
具有1个核心的输出:
18446744073709551557
real 0m23.704s
user 0m23.611s
sys 0m0.024s
原始代码(没有同步和调度开销):
package main
import (
"fmt"
"math"
)
func isOddPrime(n uint64) bool {
q := uint64(math.Sqrt(float64(n)))
for i := uint64(3); i <= q; i += 2 {
if n%i == 0 {
return false
}
}
return true
}
func main() { // find max uint64 prime
n := uint64(math.MaxUint64)
for ; !isOddPrime(n); n -= 2 {
}
fmt.Println(n) // 18446744073709551557
}
go version go1.13.4 linux/amd64
与go build -o $TMPDIR/main && time $TMPDIR/main
的输出:
18446744073709551557
real 0m24.002s
user 0m24.002s
sys 0m0.012s