История изменений
Исправление Toxo2, (текущая версия) :
Сделай отдельный map для каждого треда, потом сложи.
Да, спасибо, догадался ) Вроде работает:
package main
import (
"fmt"
"io/ioutil"
"log"
"runtime"
"sort"
"sync"
)
type StringIntStruct struct {
k string
v int
}
type ArrayOfStringIntStruct []StringIntStruct
func (a ArrayOfStringIntStruct) Len() int { return len(a) }
func (a ArrayOfStringIntStruct) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ArrayOfStringIntStruct) Less(i, j int) bool { return a[i].v > a[j].v }
func fill_data(wg *sync.WaitGroup, data []byte, start int, stop int, m map[string]int) {
defer wg.Done()
var word [1024]byte
w := 0
for i := start; i <= stop; i++ {
c := data[i] | 32
if c >= 'a' && c <= 'z' {
word[w] = c
w += 1
continue
}
if w > 0 {
m[string(word[0:w])]++
w = 0
}
}
}
func main() {
var wg sync.WaitGroup
content, err := ioutil.ReadFile("huge.txt")
if err != nil {
log.Fatal(err)
}
len_content := len(content)
num_of_cores := runtime.NumCPU()
arr_map_words := make([]map[string]int, num_of_cores)
part_content := len_content / num_of_cores
var part_start, part_stop int
part_start = 0
for core := 1; core <= num_of_cores; core++ {
part_stop = part_content * core
var bound_sym byte
for {
if part_stop >= len_content-1 {
part_stop = len_content - 1
break
}
bound_sym = content[part_stop] | 32
if bound_sym < 'a' || bound_sym > 'z' {
break
}
part_stop++
}
arr_map_words[core-1] = make(map[string]int)
wg.Add(1)
go fill_data(&wg, content, part_start, part_stop, arr_map_words[core-1])
part_start = part_stop + 1
}
wg.Wait()
map_words := arr_map_words[0]
for core := 1; core < num_of_cores; core++ {
for k, v := range arr_map_words[core] {
map_words[k] += v
}
}
count_words := len(map_words)
array_words := make(ArrayOfStringIntStruct, count_words)
w := 0
for k, v := range map_words {
array_words[w] = StringIntStruct{k, v}
w++
}
sort.Sort(array_words)
for i, word := range array_words {
if i >= 20 {
break
}
fmt.Printf("%v %v\n", word.v, word.k)
}
fmt.Printf("------------\nCount words: %d\n", count_words)
}
Но я сомневаюсь что здесь можно что-то выгадать.
Да нет, хорошо так помогает. На i3-2100 CPU @ 3.10GHz в один поток получается real 0m5,727s, а во все четыре - real 0m3,092s. Чуть не в два раза )
Я там, возможно, где-то ошибся в логике. Но принцип более/менее понял вроде ) Кажется теперь наигрался в эту игру.
--------------
А, ну для сравнения: c от vel в один поток: real 0m2,309s, с++ от kvpfs в четыре потока: real 0m2,665s
Исходная версия Toxo2, :
Сделай отдельный map для каждого треда, потом сложи.
Да, спасибо, догадался ) Вроде работает:
package main
import (
"fmt"
"io/ioutil"
"log"
"runtime"
"sort"
"sync"
)
type StringIntStruct struct {
k string
v int
}
type ArrayOfStringIntStruct []StringIntStruct
func (a ArrayOfStringIntStruct) Len() int { return len(a) }
func (a ArrayOfStringIntStruct) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ArrayOfStringIntStruct) Less(i, j int) bool { return a[i].v > a[j].v }
func fill_data(wg *sync.WaitGroup, data []byte, start int, stop int, m map[string]int) {
defer wg.Done()
var word [1024]byte
w := 0
for i := start; i <= stop; i++ {
c := data[i] | 32
if c >= 'a' && c <= 'z' {
word[w] = c
w += 1
continue
}
if w > 0 {
m[string(word[0:w])]++
w = 0
}
}
}
func main() {
var wg sync.WaitGroup
content, err := ioutil.ReadFile("huge.txt")
if err != nil {
log.Fatal(err)
}
len_content := len(content)
num_of_cores := runtime.NumCPU()
arr_map_words := make([]map[string]int, num_of_cores)
part_content := len_content / num_of_cores
var part_start, part_stop int
part_start = 0
for core := 1; core <= num_of_cores; core++ {
part_stop = part_content * core
var bound_sym byte
for {
if part_stop >= len_content-1 {
part_stop = len_content - 1
break
}
bound_sym = content[part_stop] | 32
if bound_sym < 'a' || bound_sym > 'z' {
break
}
part_stop++
}
arr_map_words[core-1] = make(map[string]int)
wg.Add(1)
go fill_data(&wg, content, part_start, part_stop, arr_map_words[core-1])
part_start = part_stop + 1
}
wg.Wait()
map_words := arr_map_words[0]
for core := 1; core < num_of_cores; core++ {
for k, v := range arr_map_words[core] {
map_words[k] += v
}
}
count_words := len(map_words)
array_words := make(ArrayOfStringIntStruct, count_words)
w := 0
for k, v := range map_words {
array_words[w] = StringIntStruct{k, v}
w++
}
sort.Sort(array_words)
for i, word := range array_words {
if i >= 20 {
break
}
fmt.Printf("%v %v\n", word.v, word.k)
}
fmt.Printf("------------\nCount words: %d\n", count_words)
}
Но я сомневаюсь что здесь можно что-то выгадать.
Да нет, хорошо так помогает. На i3-2100 CPU @ 3.10GHz в один поток получается real 0m5,727s, а во все четыре - real 0m3,092s. Чуть не в два раза )
Я там, возможно, где-то ошибся в логике. Но принцип более/менее понял вроде ) Кажется теперь наигрался в эту игру.