LINUX.ORG.RU

История изменений

Исправление 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. Чуть не в два раза )

Я там, возможно, где-то ошибся в логике. Но принцип более/менее понял вроде ) Кажется теперь наигрался в эту игру.