Попытался распараллелить "в лоб" на Golang. Правда я не уверен, что не накосячил с синхронизацией, но по идеи если массив не меняется, то получать ссылку на значение можно и без лока. Во всяком случае результирующее значение для миллиарда он считает правильное:
package main
import (
"flag"
"math"
"sync"
"sync/atomic"
)
var wg sync.WaitGroup
func calc(n uint64) uint64 {
arr := make([]uint64, n+1)
for k1 := uint64(1); k1 <= uint64(math.Sqrt(float64(n))); k1++ {
wg.Add(1)
go func(t1 uint64) {
for k2 := t1; k2 <= n/t1; k2++ {
var val uint64
if t1 != k2 {
val = t1 + k2
} else {
val = t1
}
atomic.AddUint64(&arr[t1*k2], val)
}
wg.Done()
}(k1)
}
wg.Wait()
return arr[n]
}
var maxN = flag.Uint64("max", 1000000, "max N")
func main() {
flag.Parse()
println(calc(*maxN))
}
В итоге для миллиарда получилось 111.69 sec, т.е. примерно на 40 sec быстрее, чем на C++. 0xd34df00d если будет возможность, попробуйте протестировать у себя. Интересно какой будет результат.
На мой взгляд некорректно сравнивать код оперирующий int64 с кодом оперирующим int32. Если в C++ варианте заменить int64_t на int32_t, то скорость выполнения у меня возрастает почти в два раза. Так что в данном случае надо везде long использовать.
Т.е. на моем ноуте Golang медленнее С++ чуть более чем в 2 раза. Потребление памяти одинаковое.
Кстати, еще примечательно, что C++ код выполнялся в абсолютной тишине, а от Golang кулеры завизжали как сумасшедшие. Хотя возможно, это как-то связанно со спецификой работы Benchmark в Golang.
PS Слишком долго форматировал сообщение, опередили :D
Если вы покупаете Home Edition, то вы можете выбрать еще 5 аккаунтов, у которых будет полностью такой же набор услуг. У каждого будет свой собственный 1ТБ хранилища, на своим собственном аккаунте.
Возможно он так и делает. В данном случае я больше хотел показать, что в Golang уже все необходимое для измерения производительности есть: golang.org/pkg/testing Так что нету необходимости придумывать велосипеды.
А зачем такой сложный тест? Мне кажется было бы нагляднее, если упростить его до максимума. Тем более, что Golang предоставляет такой замечательный инструмент для тестирования из коробки.
package main
import (
"testing"
"time"
)
var val1 = 10
var val2 = 1000
func longComparison(val int) bool {
time.Sleep(100 * time.Millisecond)
return true
}
func BenchmarkComplexIfDiv(b *testing.B) {
for i := 0; i < b.N; i++ {
if val1 > val2 && val1%2 == 0 {
}
}
}
func BenchmarkComplexIfConj(b *testing.B) {
for i := 0; i < b.N; i++ {
if val1 > val2 && val1&1 == 0 {
}
}
}
func BenchmarkComplexLong(b *testing.B) {
for i := 0; i < b.N; i++ {
if val1 > val2 && longComparison(val1) {
}
}
}
func BenchmarkTwoSimpleIf(b *testing.B) {
for i := 0; i < b.N; i++ {
if val1 <= val2 {
continue
}
if val1%2 == 0 {
}
}
}
// $ go test -bench .
// BenchmarkComplexIfDiv-8 2000000000 0.85 ns/op
// BenchmarkComplexIfConj-8 2000000000 0.85 ns/op
// BenchmarkComplexLong-8 2000000000 0.57 ns/op
// BenchmarkTwoSimpleIf-8 2000000000 0.58 ns/op
Кстати, забавно, но BenchmarkComplexLong такой же быстрый как и вариант с continue
А еще можно скооперироваться и взять Office 356 Home на шестерых. Тогда у каждого будет по полному пакету офиса и 1ТБ хранилища за $1.4 (90 руб) в месяц. Собственно, именно это я и сделал.
P.S. Ах да, еще это включает 60 минут Skype в месяц. Звонить можно во многие страны, в частности в Россию можно тоже, но только на стационарные телефоны. Однако я этим совершенно не пользуюсь.
Дело в том, что const — это не константа, а именно read-only переменная. Как правило, константам можно присваивать только скалярные значения, переменной же const в JS можно присвоить любой объект. Кроме того, const можно использовать и в циклах, если это перечисление. Например следующий код будет прекрасно работать:
const fruits = ["apple", "banana", "orange"];
for (const fruit of fruits) {
console.log(fruit);
// fruit = "dog" вызовет: TypeError: Assignment to constant variable.
}
Еще одна причина почему лучше везде где возможно использовать const, это интроспекция в IDE. Например, в TypeScript следующая проверка будет работать:
const eventHandler: Function | null = getHandler();
if (eventHandler === null) {
return;
}
// с этого места eventHandler имеет тип Function
// ... много кода
// можно безопасно вызывать
// eventHandler - точно не null
eventHandler();
А если же заменить const eventHandler на let eventHandler, то код не скомпилируется, поскольку между первичной проверкой на null и вызовом eventHandler() мог присвоиться null уже где-то в другом месте.
Я бы рекомендовал игру Choice of Robots. Это не визуальная новелла, а текстовая адвенчура без единой картинки. Но сюжет настолько разнообразный и интересный, что игра просто захватывает с первых минут.
Английский язык там бывает местами сложный, но в большинстве своем читается на одном дыхании. Небольшой отрывок в качестве примера (прим. Arniel — это имя моего робота):
…
You realize you're driving yourself crazy by sitting here listening to this output, which will be only a tiny portion of the overall data. You decide to take a long walk around Stanford's campus. It's a nice day out and when you return, Arniel has moved on to the topic of which vegetables go best in a savory crepe.
But for better or for worse, Arniel appears to be ingesting the spirit of the Internet: obsessed with minutia, occasionally factually incorrect, and mistrustful of authority. (-Military) (++Autonomy)
You leave the program running overnight. When you wake up the next morning, you ask Arniel, «How do you feel?»
«Confused and angry,» says Arniel. «But also smart.»
You're ecstatic—you never programmed Arniel to say anything like that.
«Is the United States a good guy or a bad guy, Master?» Arniel asks. «I am confused about this. Some people seem very convinced one way or the other.»
Arniel is even trying to make ethical decisions! This is all very exciting. But what will you say?
«The United States government in itself is neither good nor evil. It is simply powerful; and the people in it choose every day to use that power for good or evil.»
«It seems that it is good to be powerful,» Arniel ventures.
«Yes,» you say darkly.
«The optimal strategy appears to be to become powerful first, and decide whether to be good or evil later,» Arniel says.
«Are you planning to become powerful, then?» you say to Arniel, slightly amused.
Arniel nods and says earnestly, «Yes.» (+++Autonomy) (+Military)
Попытался распараллелить "в лоб" на Golang. Правда я не уверен, что не накосячил с синхронизацией, но по идеи если массив не меняется, то получать ссылку на значение можно и без лока. Во всяком случае результирующее значение для миллиарда он считает правильное:
В итоге для миллиарда получилось 111.69 sec, т.е. примерно на 40 sec быстрее, чем на C++. 0xd34df00d если будет возможность, попробуйте протестировать у себя. Интересно какой будет результат.
Заменил int64 на uint64 и результат получился значительно лучше:
Я думаю Golang достаточно умный чтобы выполнить это один раз. Попробовал вынести это в переменную, но не заметил разницы.
Я компилировал ваш код с теми же аргументами:
clang++ -O3 -march=native -o habr-test-cpp ./habr-test-1.cpp
. Правда, судя по всему, у меня clang 6Вариант на Golang:
И результат на моем древнем ноутбуке с Intel® Core(TM) i7-2860QM CPU @ 2.50GHz и 16 Gb оперативки:
При этом С++ вариант у меня выполняется:
Т.е. на моем ноуте Golang медленнее С++ чуть более чем в 2 раза. Потребление памяти одинаковое.
Кстати, еще примечательно, что C++ код выполнялся в абсолютной тишине, а от Golang кулеры завизжали как сумасшедшие. Хотя возможно, это как-то связанно со спецификой работы Benchmark в Golang.
PS Слишком долго форматировал сообщение, опередили :D
А зачем такой сложный тест? Мне кажется было бы нагляднее, если упростить его до максимума. Тем более, что Golang предоставляет такой замечательный инструмент для тестирования из коробки.
Кстати, забавно, но BenchmarkComplexLong такой же быстрый как и вариант с continue
P.S. Ах да, еще это включает 60 минут Skype в месяц. Звонить можно во многие страны, в частности в Россию можно тоже, но только на стационарные телефоны. Однако я этим совершенно не пользуюсь.
git stash
— отложить все текущие изменения в локальное хранилищеgit stash pop
— забрать последние сохраненные изменения из хранилищаПолезно если вы не хотите пока комитить код, но вам срочно нужно переключится на другую ветку.
Если вы про то, что ключевое слово
const
для определения read-only переменных было выбрано неудачно и вносит путаницу, то тут я полностью согласен.Дело в том, что
const
— это не константа, а именно read-only переменная. Как правило, константам можно присваивать только скалярные значения, переменной жеconst
в JS можно присвоить любой объект. Кроме того,const
можно использовать и в циклах, если это перечисление. Например следующий код будет прекрасно работать:Еще одна причина почему лучше везде где возможно использовать
const
, это интроспекция в IDE. Например, в TypeScript следующая проверка будет работать:А если же заменить
const eventHandler
наlet eventHandler
, то код не скомпилируется, поскольку между первичной проверкой наnull
и вызовомeventHandler()
мог присвоитьсяnull
уже где-то в другом месте.Кстати, похожее декларирование переменных есть в Kotlin, только там используются ключевые слова
var
,val
.https://kotlinlang.org/docs/reference/basic-syntax.html#defining-variables
Английский язык там бывает местами сложный, но в большинстве своем читается на одном дыхании. Небольшой отрывок в качестве примера (прим. Arniel — это имя моего робота):
…
You realize you're driving yourself crazy by sitting here listening to this output, which will be only a tiny portion of the overall data. You decide to take a long walk around Stanford's campus. It's a nice day out and when you return, Arniel has moved on to the topic of which vegetables go best in a savory crepe.
But for better or for worse, Arniel appears to be ingesting the spirit of the Internet: obsessed with minutia, occasionally factually incorrect, and mistrustful of authority. (-Military) (++Autonomy)
You leave the program running overnight. When you wake up the next morning, you ask Arniel, «How do you feel?»
«Confused and angry,» says Arniel. «But also smart.»
You're ecstatic—you never programmed Arniel to say anything like that.
«Is the United States a good guy or a bad guy, Master?» Arniel asks. «I am confused about this. Some people seem very convinced one way or the other.»
Arniel is even trying to make ethical decisions! This is all very exciting. But what will you say?
«The United States government in itself is neither good nor evil. It is simply powerful; and the people in it choose every day to use that power for good or evil.»
«It seems that it is good to be powerful,» Arniel ventures.
«Yes,» you say darkly.
«The optimal strategy appears to be to become powerful first, and decide whether to be good or evil later,» Arniel says.
«Are you planning to become powerful, then?» you say to Arniel, slightly amused.
Arniel nods and says earnestly, «Yes.» (+++Autonomy) (+Military)