Go : параллельное выполнение

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go : параллельное выполнение

Непрочитанное сообщение Olej » 11 фев 2022, 01:29

Olej писал(а):
20 янв 2022, 00:55
P.S. Начав с того, что просто начисто поменялось сравнительно с версией Golang 1.5, когда писался конспект...
В Go множество интересных и новых вещей...
Но для меня (в круге моих интересов) главное, из-за чего я возился и вожусь с Go - это возможность параллелизма и эффективного распараллеливания выполнения на многопроцессорах, SMP, многоядерных компьютерах!
Olej писал(а):
20 янв 2022, 00:55
По результатам этих разбирательств мной даже был написан конспект
Читая конспект (свой :lol: ) читаю там написанное в 2012 году - когда начиналась работа над Go и над конспектом ... по заказу софтверной компании GlobalLogic:
Некоторыми из заявленных целей разработки были:
...
- Естественным образом отобразить в языке возможность параллельных вычислений в многопроцессорных (SMP, многоядерных) системах.
Таким образом, язык Go предвосхитил (к началу разработки в 2007 году это ещё не было очевидным) тотальный переход всего компьютерного железа на многоядерность (многопроцессорность) и возможности параллельной обработки на многих процессорах. И то, что в ближайшее время совершенно ординарной настольной архитектурой может стать даже не 2-4 ядра, а 16, 32, или 64. В этом язык Go в чём то наследует философию процедурного языка параллельного программирования Occam, разработанному в начале 1980-х годов для программирования транспьютеров.
И вот за эти годы сбылся прогноз, у многих на рабочем столе стоит компьютер с несколькими десятками ядер... Но все (практически) предыдущие языки и их реализации не могут эффективно поддерживать такие архитектуры ... что (и почему) постараюсь оказать далее.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 01:33

Olej писал(а):
11 фев 2022, 01:29
Но все (практически) предыдущие языки и их реализации не могут эффективно поддерживать такие архитектуры ... что (и почему) постараюсь оказать далее.
Поддержке параллельности и многопроцессорности в традиционных (предыдущих) языках программирования в Linux я в своё врмя посвятил книгу (в электронном виде), которую для ознакомления и сравнения можно взять здесь: Параллелизм, конкурентность, многопроцессорность в Linux
Номер последней редакции: 06
Объём (страниц): 97
Размер файла текста: 186356
Размер архива кодов: 314873
Дата размещения: 19 июня 2018
Ну и в тему - моя книга, изданная в Санкт-Петербурге:
Изображение
QNX/UNIX: анатомия параллелизма
ISBN: 5-93286-088-X
288 страниц
декабрь 2005
Символ-Плюс
Книгу можно свободно скачать здесь: Flibusta

P.S. Книгу я упоминаю здесь потому что ...
а). куда не зайду на фирму - у всех вижу лежащую эту свою книгу ... издательство "Символ-Плюс" в Санкт-Петербурге, предполагаю, делало допечатку тиража книги (а откуда их столько?) ... и мне ничего не доплачивало в качестве гонорара за дополнительные тиражи :lol: :twisted:
б). по нескольким звучащим в Интернет отзывам эту книгу называли как "лучшее, что написано о предмете на русском языке". ;-)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 01:58

Olej писал(а):
11 фев 2022, 01:29
... что (и почему) постараюсь оказать далее.
По механизму планирования параллельного выполнения в Go существует замечательная статья непосредственно от автора реализации, которая много разъясняет ... вот ссылка в моём блоге: Планирование параллельного исполнения в Go
Утверждается, что после версии GoLang 1.1 (2012г.-2013г.) этот механизм Go-рутин радикально переделан, улучшен и сделан ещё существенно более эффективным, чем ранее.

Теперь используется алгоритм планирования с заимствованием работ (в оригинале даже "воровством работ", но в русскоязычной терминологии уже установился благозвучный термин заимствование). Обстоятельнейший (на 29 страниц) анализ самих принципов, на которых построен этот механизм, описан в Scheduling Multithreaded Computations by Work Stealing. Там же проведе сложнейший и детальный математический анализ производительности.

Коротко ("на пальцах") механизм описан в заметке The Go scheduler (by Daniel Morsing 30 June 2013). Это настолько интересно, что мной сделан перевод этой заметки, который вы можете найти на странице Диспетчер Go.
Изображение

К сожалению, перевод этот свой (последняя ссылка) я подарил хлопчикам-самопальщикам с сайта http://4gophers.ru ... но они, как это всегда водится у недоумков, просрали и сайт и публикацию. и свой интерес к Go.. :-? :evil:
Если я найду этот перевод, то помещу ссылки сюда.

P.S. Нашёлся мой перевод: ДИСПЕТЧЕР GO
19-10-2015
Только он размещён бездарно :cry: - там выпали все поясняющие картинки. Но картинки можно взять из оригинальной статьи.

P.P.S. Я просто восстановил текст, чтобы не зависеть впредь от разных криворуких :oops:
Вложения
ДиспетчерGo.01.odt
(209.58 КБ) 79 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 11:46

Olej писал(а):
11 фев 2022, 01:29
Но все (практически) предыдущие языки и их реализации не могут эффективно поддерживать такие архитектуры ... что (и почему) постараюсь оказать далее.
Исторически многопроцессорность (SMP) первоначально тспользовали через разделение процессоров между задачами (процессами), в UNIX-like системах посредством fork().

Следующим шагом стало использование потоков, POSIX pthread_t + конкурентное (вытесняющее) диспетчирование потоков со стороны операционной системы. При этом подходе, и это так формулируется во многих публикациях, код приложения можно написать так чтобы он использовал (в одном процессе, задаче) все доступные в железе процессоры.
Olej писал(а):
11 фев 2022, 01:58
Коротко ("на пальцах") механизм описан в заметке The Go scheduler (by Daniel Morsing 30 June 2013).
Параллельность в Go построена на том, что N ветвей на M процессорах (N>M или N>>M) распределяются равномерно в качестве сопрограмм, диспетчирующихся на кооперативной многозадачности. На Go не нужно писать код чтобы он использовал SMP, а код ... точнее даже бинарный скомпилированный код, один и тот же на разном оборудовании... будет сам выполняться так, чтобы использовать все процессоры (или указанное окружением число).

P.S. Кооперативная многопоточность, или сопрограммы, позже получила новый всплеск интереса и в старых инструментах ... см. C++: корутины.

В Go происходит истинное масштабирование: бинарный код, переносимый с компьютера на компьютер, на каждом месте распределяется на столько процессоров, сколько их есть в наличии.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 11:55

Olej писал(а):
11 фев 2022, 11:46
В Go происходит истинное масштабирование: бинарный код, переносимый с компьютера на компьютер, на каждом месте распределяется на столько процессоров, сколько их есть в наличии.
А теперь самое время проверить и проиллюстрировать как это - в коде... Пока то что есть ;-) :

Код: Выделить всё

package main

import (
	"fmt"
	"flag"
	"math"
	"time"
	"sync"
	"runtime"
)

func main() {
	var branch int
	flag.IntVar(&branch, "b", 30, "number of parallel branches")
	useDebug := flag.Bool("v", false, "increase verbosity")
	flag.Parse()

	activDo := func(n int64) {   // активная рабочая функция
		var β, θ float64 = 0.0, math.Pi / 2
		for n != 0 { 
			β += math.Sin(θ)
			θ *= 1.1
			n--
		}
	}
	const norma = 100000000
	start := time.Now()
	activDo(int64(norma))        // калибровка
	var dt time.Duration
	dt = time.Since(start)

	множитель := float64(time.Second) / float64(dt) * norma
	индекс := int64(math.Round(множитель))
	if *useDebug {
		fmt.Printf("вызов калибровки: %dns | %f s\n", dt, dt.Seconds())
		fmt.Printf("множитель=%f\n", множитель)
		fmt.Printf("индекс для 1s = %d\n", индекс)
	}

	start = time.Now()
	activDo(индекс)              // единичное выполнение
	dt = time.Since(start)
	fmt.Printf("единичное выполнение:  %dns | %f s\n", dt, dt.Seconds())

   fmt.Printf("число процессоров в системе: %v\n", runtime.NumCPU())
	var wg sync.WaitGroup
	fmt.Printf("Выполнение %d ветвей...\n", branch)
	start = time.Now()
	for branch > 0 {
		wg.Add(1)    // увеличиваем WaitGroup счетчик
		go func() {
			defer wg.Done() // уменьшаем счетчик когда goroutine завершается
			if *useDebug {
				fmt.Println("Старт ", branch, time.Now())
			}
			activDo(индекс)
			if *useDebug {
				fmt.Println("Финиш ", branch, time.Now())
			}
		}()
		branch--
	}
	wg.Wait()       // ожидаем завершения всех goroutine
	dt = time.Since(start)
	fmt.Printf("... потребовало: %dns | %fs\n", dt, dt.Seconds())
}
Идея здесь:
- имеем активную работу (обязательно активную, без блокирования со стороны операционной системы и без системных вызовов) - фнкция activDo ...
- запускаем её на текущем процессор и выясняем сколько раз (с каким аргументом) её нужно запускать в едином потоке, чтобы она выполнялась ровно за 1 секунду...
- после этого запускаем много ветвей (опция -b команды запуска программы), каждая из которых потребует вычислительной работы ровно на 1 секунду.

Код: Выделить всё

olej@R420:~/2022/Go/probes$ go fmt mtime.go
mtime.go

Код: Выделить всё

olej@R420:~/2022/Go/probes$ go build mtime.go

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ ./mtime -h
Usage of ./mtime:
  -b int
    	number of parallel branches (default 30)
  -v	increase verbosity
Вложения
mtime.go
(1.76 КБ) 54 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 12:33

Olej писал(а):
11 фев 2022, 11:55
Идея здесь:
Начинаю с процессора с малым (относительно) числом (4) процессоров:

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ inxi -Cxxx
CPU:       Topology: Dual Core model: Intel Core i5 660 bits: 64 type: MT MCP arch: Nehalem rev: 5 L2 cache: 4096 KiB
           flags: lm nx pae sse sse2 sse3 sse4_1 sse4_2 ssse3 vmx bogomips: 26601
           Speed: 1472 MHz min/max: N/A Core speeds (MHz): 1: 1472 2: 1290 3: 1253 4: 1528
Но обращаем внимание, что из 4-х ядер здесь физических - 2, а остающиеся 2 - это гипертрэдинг:

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ lscpu
Архитектура:                     x86_64
CPU op-mode(s):                  32-bit, 64-bit
Порядок байт:                    Little Endian
Address sizes:                   36 bits physical, 48 bits virtual
CPU(s):                          4
On-line CPU(s) list:             0-3
Потоков на ядро:                 2
Ядер на сокет:                   2
Сокетов:                         1
NUMA node(s):                    1
ID прроизводителя:               GenuineIntel
Семейство ЦПУ:                   6
Модель:                          37
Имя модели:                      Intel(R) Core(TM) i5 CPU         660  @ 3.33GHz
Степпинг:                        5
CPU МГц:                         1464.438
BogoMIPS:                        6650.38
Виртуализация:                   VT-x
L1d cache:                       64 KiB
L1i cache:                       64 KiB
L2 cache:                        512 KiB
L3 cache:                        4 MiB
NUMA node0 CPU(s):               0-3
Vulnerability Itlb multihit:     KVM: Mitigation: Split huge pages
Vulnerability L1tf:              Mitigation; PTE Inversion; VMX conditional cache flushes, SMT vulnerable
Vulnerability Mds:               Vulnerable: Clear CPU buffers attempted, no microcode; SMT vulnerable
Vulnerability Meltdown:          Mitigation; PTI
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; Full generic retpoline, IBPB conditional, IBRS_FW, STIBP conditional, RSB filling
Vulnerability Srbds:             Not affected
Vulnerability Tsx async abort:   Not affected
Флаги:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ht tm pbe sysca
                                 ll nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes
                                 64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 popcnt aes lahf_lm pti ssbd ibrs ibpb stibp tpr_
                                 shadow vnmi flexpriority ept vpid dtherm ida arat flush_l1d
И производительность этих гипертрэдинговых процессоров будет радикально ниже на тех же однотипных задачах: нумерация ядер процессоров:

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ lscpu -e
CPU NODE SOCKET CORE L1d:L1i:L2:L3 ONLINE
  0    0      0    0 0:0:0:0           да
  1    0      0    0 0:0:0:0           да
  2    0      0    1 1:1:1:0           да
  3    0      0    1 1:1:1:0           да

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 12:39

Olej писал(а):
11 фев 2022, 12:33
Начинаю с процессора с малым (относительно) числом (4) процессоров:

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ ./mtime -v -b 2 
вызов калибровки: 483744891ns | 0.483745 s
множитель=206720529.478419
индекс для 1s = 206720529
единичное выполнение:  1000286500ns | 1.000287 s
число процессоров в системе: 4
Выполнение 2 ветвей...
Старт  0 2022-02-11 11:34:50.94436817 +0200 EET m=+1.484215892
Старт  0 2022-02-11 11:34:50.944372152 +0200 EET m=+1.484219884
Финиш  0 2022-02-11 11:34:51.953226068 +0200 EET m=+2.493073812
Финиш  0 2022-02-11 11:34:51.955465461 +0200 EET m=+2.495313198
... потребовало: 1011148195ns | 1.011148s
Сопрограммы стартуют и завершаются практически одновременно!
Все процессоры, включая гипертрэдинговые:

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ ./mtime -b 4 
единичное выполнение:  1000603765ns | 1.000604 s
число процессоров в системе: 4
Выполнение 4 ветвей...
... потребовало: 1880313667ns | 1.880314s
Пошли увеличивать число параллельных ветвей:

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ ./mtime -b 8
единичное выполнение:  1000362102ns | 1.000362 s
число процессоров в системе: 4
Выполнение 8 ветвей...
... потребовало: 3754303337ns | 3.754303s

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ ./mtime -b 12
единичное выполнение:  996771949ns | 0.996772 s
число процессоров в системе: 4
Выполнение 12 ветвей...
... потребовало: 5777848627ns | 5.777849s

Код: Выделить всё

olej@nvidia:~/2022/Go/probes$ ./mtime -b 16
единичное выполнение:  998857506ns | 0.998858 s
число процессоров в системе: 4
Выполнение 16 ветвей...
... потребовало: 7527535160ns | 7.527535s
Всё очень кратно числу параллельных ветвей делённому на 4.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 13:13

Olej писал(а):
11 фев 2022, 12:33
Начинаю с процессора с малым (относительно) числом (4) процессоров:
Переношу тот же бинарный исполнимый файл (без перекомпиляций) на такой вот серверный процессор ... движемся в сторону умощнения - 8 процессоров:

Код: Выделить всё

olej@ESPRIMO:~$ inxi -Cxxx
CPU:       Topology: Quad Core model: Intel Xeon E3-1240 v3 bits: 64 type: MT MCP arch: Haswell rev: 3 L2 cache: 8192 KiB 
           flags: avx avx2 lm nx pae sse sse2 sse3 sse4_1 sse4_2 ssse3 vmx bogomips: 54275 
           Speed: 3592 MHz min/max: 800/3800 MHz Core speeds (MHz): 1: 3592 2: 3592 3: 3592 4: 3592 5: 3592 6: 3592 7: 3592 
           8: 3592 
Тоже гипертрэдинг ... он сейчас везде - ведь это самый эффективный способ продавать воздух :lol: :

Код: Выделить всё

olej@ESPRIMO:~$ lscpu
Архитектура:                     x86_64
CPU op-mode(s):                  32-bit, 64-bit
Порядок байт:                    Little Endian
Address sizes:                   39 bits physical, 48 bits virtual
CPU(s):                          8
On-line CPU(s) list:             0-7
Потоков на ядро:                 2
Ядер на сокет:                   4
Сокетов:                         1
NUMA node(s):                    1
ID прроизводителя:               GenuineIntel
Семейство ЦПУ:                   6
Модель:                          60
Имя модели:                      Intel(R) Xeon(R) CPU E3-1240 v3 @ 3.40GHz
Степпинг:                        3
CPU МГц:                         3591.745
CPU max MHz:                     3800,0000
CPU min MHz:                     800,0000
BogoMIPS:                        6784.40
Виртуализация:                   VT-x
L1d cache:                       128 KiB
L1i cache:                       128 KiB
L2 cache:                        1 MiB
L3 cache:                        8 MiB
NUMA node0 CPU(s):               0-7
Vulnerability Itlb multihit:     KVM: Mitigation: Split huge pages
Vulnerability L1tf:              Mitigation; PTE Inversion; VMX conditional cache flushes, SMT vulnerable
Vulnerability Mds:               Mitigation; Clear CPU buffers; SMT vulnerable
Vulnerability Meltdown:          Mitigation; PTI
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; Full generic retpoline, IBPB conditional, IBRS_FW, STIBP conditional, RSB filling
Vulnerability Srbds:             Mitigation; Microcode
Vulnerability Tsx async abort:   Not affected
Флаги:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe
                                  syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf p
                                 ni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt
                                  tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_s
                                 hadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat p
                                 ln pts md_clear flush_l1d

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 14:03

Olej писал(а):
11 фев 2022, 13:13
серверный процессор
Olej писал(а):
11 фев 2022, 13:13
8 процессоров

Код: Выделить всё

olej@ESPRIMO:~/2022/Go/probes$ ./mtime -b 2
единичное выполнение:  1001123225ns | 1.001123 s
число процессоров в системе: 8
Выполнение 2 ветвей...
... потребовало: 1000789337ns | 1.000789s

Код: Выделить всё

olej@ESPRIMO:~/2022/Go/probes$ ./mtime -b 4
единичное выполнение:  1000675031ns | 1.000675 s
число процессоров в системе: 8
Выполнение 4 ветвей...
... потребовало: 1072395928ns | 1.072396s

Код: Выделить всё

olej@ESPRIMO:~/2022/Go/probes$ ./mtime -b 6
единичное выполнение:  999122657ns | 0.999123 s
число процессоров в системе: 8
Выполнение 6 ветвей...
... потребовало: 1358375459ns | 1.358375s

Код: Выделить всё

olej@ESPRIMO:~/2022/Go/probes$ ./mtime -b 8
единичное выполнение:  1001123846ns | 1.001124 s
число процессоров в системе: 8
Выполнение 8 ветвей...
... потребовало: 1633993462ns | 1.633993s

Код: Выделить всё

olej@ESPRIMO:~/2022/Go/probes$ ./mtime -b 16
единичное выполнение:  1000649876ns | 1.000650 s
число процессоров в системе: 8
Выполнение 16 ветвей...
... потребовало: 3136992990ns | 3.136993s

Код: Выделить всё

olej@ESPRIMO:~/2022/Go/probes$ ./mtime -b 24
единичное выполнение:  1001247708ns | 1.001248 s
число процессоров в системе: 8
Выполнение 24 ветвей...
... потребовало: 4793425236ns | 4.793425s

Код: Выделить всё

olej@ESPRIMO:~/2022/Go/probes$ ./mtime -b 32
единичное выполнение:  999853762ns | 0.999854 s
число процессоров в системе: 8
Выполнение 32 ветвей...
... потребовало: 6125756770ns | 6.125757s
Картина ясная - до 8 ветвей время выполнения практически не растёт, ветви выполняются параллельно на разных процессорах. Дальше время увеличивается от числа ветвей выполнения в кратности 8.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Go (продолжение)

Непрочитанное сообщение Olej » 11 фев 2022, 14:55

Olej писал(а):
11 фев 2022, 13:13
движемся в сторону умощнения
Ну и, наконец, настоящий SMP - 1U сервер DELL R420 - 2 процессора по 20 ядер каждый, из которых 10 физических + 10 гипертрэдинговых:

Код: Выделить всё

olej@R420:~/2022/Go/probes$ inxi -Cxxx
CPU:       Topology: 2x 10-Core model: Intel Xeon E5-2470 v2 bits: 64 type: MT MCP SMP arch: Ivy Bridge rev: 4 
           L2 cache: 50.0 MiB 
           flags: avx lm nx pae sse sse2 sse3 sse4_1 sse4_2 ssse3 vmx bogomips: 192097 
           Speed: 2800 MHz min/max: 1200/3200 MHz Core speeds (MHz): 1: 2800 2: 2800 3: 2800 4: 2800 5: 2800 6: 2800 7: 2800 
           8: 2800 9: 2799 10: 2800 11: 2802 12: 2800 13: 2800 14: 2800 15: 2800 16: 2800 17: 2800 18: 2799 19: 2800 20: 2803 
           21: 2799 22: 2804 23: 2800 24: 2800 25: 2798 26: 2800 27: 2800 28: 2800 29: 2802 30: 2800 31: 2800 32: 2800 
           33: 2800 34: 2800 35: 2800 36: 2800 37: 2800 38: 2800 39: 2800 40: 2800 
Увеличиваю приоритет, с помощью nice, для сильно рассредоточенной системы:

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 2
единичное выполнение:  746385311ns | 0.746385 s
число процессоров в системе: 40
Выполнение 2 ветвей...
... потребовало: 1052282711ns | 1.052283s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 4
единичное выполнение:  988448898ns | 0.988449 s
число процессоров в системе: 40
Выполнение 4 ветвей...
... потребовало: 1050231944ns | 1.050232s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 8
единичное выполнение:  992893109ns | 0.992893 s
число процессоров в системе: 40
Выполнение 8 ветвей...
... потребовало: 1110658341ns | 1.110658s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 19
единичное выполнение:  695376305ns | 0.695376 s
число процессоров в системе: 40
Выполнение 19 ветвей...
... потребовало: 979487630ns | 0.979488s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 25
единичное выполнение:  959440888ns | 0.959441 s
число процессоров в системе: 40
Выполнение 25 ветвей...
... потребовало: 1393401498ns | 1.393401s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 40
единичное выполнение:  760297726ns | 0.760298 s
число процессоров в системе: 40
Выполнение 40 ветвей...
... потребовало: 1349117658ns | 1.349118s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 80
единичное выполнение:  641925681ns | 0.641926 s
число процессоров в системе: 40
Выполнение 80 ветвей...
... потребовало: 2478083613ns | 2.478084s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 120
единичное выполнение:  625304809ns | 0.625305 s
число процессоров в системе: 40
Выполнение 120 ветвей...
... потребовало: 3618422589ns | 3.618423s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 160
единичное выполнение:  637959344ns | 0.637959 s
число процессоров в системе: 40
Выполнение 160 ветвей...
... потребовало: 4624825501ns | 4.624826s

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 200
единичное выполнение:  635790957ns | 0.635791 s
число процессоров в системе: 40
Выполнение 200 ветвей...
... потребовало: 5778834978ns | 5.778835s
В последнем случае мы наблюдаем как 200 параллельных ветвей разделяют мощности 40 процессоров.
Время выполнения многих ветвей (длительностью 1с) в сумме - пропорционально кратности числа ветвей числу процессоров (40).
P.S. Конечно, времена несколько "гуляют", могут быть выбросы и показаны только средние результаты ... но даже там где "выпадает" (а это есть как в плюс, так и в минус), это происходит незначительно.
P.P.S. Это связано с особенностями диспетчирования потоков в системе Linux ( O(1) ), и несколько специфичным толкованием в Linux понятия приоритетов и nice... Более точно можно это посмотреть можно запуская программу с приоритетом реального времени (chrt - редкие полезные команды)

Код: Выделить всё

olej@R420:~/2022/Go/probes$ sudo nice -19 ./mtime -b 1000
единичное выполнение:  632881435ns | 0.632881 s
число процессоров в системе: 40
Выполнение 1000 ветвей...
... потребовало: 28299636371ns | 28.299636s
28,299636÷(1000÷40) = 1,132 - что лишний раз подтверждает описываемую модель с высокой точностью: 1000 параллельных ветвей распределяются по 40 процессорам в среднем по 25 штук на процессор, выполняются на каждом процессоре последовательно, и выполняются (в среднем) в те же 25 раз длиннее.

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей