суббота, 8 февраля 2020 г.

Прошу прощения

    Не смотря на то, что я почти закончил версию 0.2(осталось доделать только каналы, на подобии того как они сделаны в go), я все больше сталкиваюсь с тем что различные вещи начинают меня смущать:
  • Мне не хватает нормального ООП.
  • Мне не нравится что данными из модулей можно манипулировать. Я сам это часто использую, но почти всегда это связанно с компенсацией того, что в язые нет полноценного ООП.
  • Хотелось бы чтобы требования групп проверялись во время компиляции, а из-за особенностей языка это не возможно.
  • Я постоянно упираюсь в особенности языка Си. Мне постоянно хочется вернуться на LLVM IR.
  • Мне не хватает гибкости cine, постоянно приходится делать какие то builtIn вещи в компиляторе или использовать код на Си.
  • Мне не нравится работа с ошибками в cine.
  • Хотя изначально я делал язык в том числе ради производительности и во многих местах где надо было выбрать производительность или удобство, я выбирал производительность, сейчас бы я принял другие решения. С годами мне удобство стало важнее. Не говоря о том, что можно не выбирать ведь по сути 95% времени программы работает 5% кода и эти 5% просто можно оптимизировать (если есть подходящие инструменты).
    Подумав я понял, что бессмысленно продолжать это безумие. И решил писать новый язык с нуля.
    Прошу прощения за то, что отнял время у всех тех кто уже начал изучать язык.
    Через некоторое время я удалю этот блог и git аккаунт.
    Но напоследок мне захотелось узнать производительность программ написанных на cine.

    Для тестирования я выбрал бенчмарк nbody -  https://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/nbody.html
    Поскольку на cine  можно хоть все функции писать на Си, нет никакого смысла сравнивать оптимизированные версии, поэтому я взял самые производительные вариант программ которые решают задачу "в лоб" без особых оптимизаций. Не привожу на них ссылки поскольку я эту статью пишу второй раз (blogger - это нечто) и искать заново я не хочу. Я выбрал программы написанные на go, c, rust, python. Так же я ради интереса включил самые оптимизированные варианты (они на си и rust). Все программы на си (включая ту которая сгенерирована с помощью cine) буду компилироваться с помощью clang и gcc, а также на трёх уровнях оптимизации. Программы на rust также будут скомпилированы с тремя уровнями оптимизации.
    Вот программа написанная на cine (основана на не оптимизированном варианте написанном на Си):

func solarMass() Float64
    attributes
        alwaysInline
    result = 4.0 * Float64.pi() * Float64.pi()

func daysPerYear() Float64
    attributes
        alwaysInline
    result = 365.24

type Planet
    x, y, z Float64
    vx, vy, vz Float64
    mass Float64

proc advance(:bodies [Planet])
    for i := 0; i < bodies.getLength(); i++
        b := bodies[i]
        for j := i + 1; j < bodies.getLength(); j++
            b2 := bodies[j]
            dx .= b.x - b2.x
            dy .= b.y - b2.y
            dz .= b.z - b2.z
            invDistance .= 1.0 / sqrt(dx * dx + dy * dy + dz * dz)
            mag .= invDistance * invDistance * invDistance
            b:vx -= dx * b2.mass * mag
            b:vy -= dy * b2.mass * mag
            b:vz -= dz * b2.mass * mag
            b2:vx += dx * b.mass * mag
            b2:vy += dy * b.mass * mag
            b2:vz += dz * b.mass * mag
            bodies:setItem(i, b)
            bodies:setItem(j, b2)
    for i := 0; i < bodies.getLength(); i++
        b := bodies[i]
        b:x += b.vx.clone()
        b:y += b.vy.clone()
        b:z += b.vz.clone()
        bodies:setItem(i, b)

func energy(bodies [Planet]) Float64
    for i := 0; i < bodies.getLength(); i++
        b .= bodies[i]
        result += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz)
        for j := i + 1; j < bodies.getLength(); j++
            b2 .= bodies[j]
            dx .= b.x - b2.x
            dy .= b.y - b2.y
            dz .= b.z - b2.z
            distance .= sqrt(dx * dx + dy * dy + dz * dz)
            result -= (b.mass * b2.mass) / distance

proc offsetMomentum(:bodies [Planet])
    px := 0.0
    py := 0.0
    pz := 0.0
    parse _, body <- bodies
        px += body.vx * body.mass
        py += body.vy * body.mass
        pz += body.vz * body.mass
    first := bodies.getFirst()
    first:vx = !px / solarMass()
    first:vy = !py / solarMass()
    first:vz = !pz / solarMass()
    bodies:setFirst(first)

func bodies() [Planet]
    attributes
        alwaysInline
    result = [Planet].init(5)
    sm .= solarMass()
    dpy .= daysPerYear()
    C
        double solar_mass = sm_;
        double days_per_year = dpy_;
        ##Planet## bodies[5] = {
            {                               /* sun */
                .x_ = 0, .y_ = 0, .z_ = 0, .vx_ = 0, .vy_ = 0, .vz_ = 0, .mass_ = solar_mass
            },
            {                               /* jupiter */
                .x_ = 4.84143144246472090e+00,
                .y_ = -1.16032004402742839e+00,
                .z_ = -1.03622044471123109e-01,
                .vx_ = 1.66007664274403694e-03 * days_per_year,
                .vy_ = 7.69901118419740425e-03 * days_per_year,
                .vz_ = -6.90460016972063023e-05 * days_per_year,
                .mass_ = 9.54791938424326609e-04 * solar_mass
            },
            {                               /* saturn */
                .x_ = 8.34336671824457987e+00,
                .y_ = 4.12479856412430479e+00,
                .z_ = -4.03523417114321381e-01,
                .vx_ = -2.76742510726862411e-03 * days_per_year,
                .vy_ = 4.99852801234917238e-03 * days_per_year,
                .vz_ = 2.30417297573763929e-05 * days_per_year,
                .mass_ = 2.85885980666130812e-04 * solar_mass
            },
            {                               /* uranus */
                .x_ = 1.28943695621391310e+01,
                .y_ = -1.51111514016986312e+01,
                .z_ = -2.23307578892655734e-01,
                .vx_ = 2.96460137564761618e-03 * days_per_year,
                .vy_ = 2.37847173959480950e-03 * days_per_year,
                .vz_ = -2.96589568540237556e-05 * days_per_year,
                .mass_ = 4.36624404335156298e-05 * solar_mass
            },
            {                               /* neptune */
                .x_ = 1.53796971148509165e+01,
                .y_ = -2.59193146099879641e+01,
                .z_ = 1.79258772950371181e-01,
                .vx_ = 2.68067772490389322e-03 * days_per_year,
                .vy_ = 1.62824170038242295e-03 * days_per_year,
                .vz_ = -9.51592254519715870e-05 * days_per_year,
                .mass_ = 5.15138902046611451e-05 * solar_mass
            }
        };
        for (int i = 0; i < 5; i++){
            result_.items[i] = bodies[i];
        }

func dt() Float64
    attributes
        alwaysInline
    result = 0.01

func recipDT() Float64
    attributes
        alwaysInline
    result = 1.0 / dt()

proc scaleBodies(:bodies [Planet], scale Float64)
    for i := 0; i < bodies.getLength(); i++
        body := bodies[i]
        body:mass *= scale * scale
        body:vx *= scale
        body:vy *= scale
        body:vz *= scale
        bodies:setItem(i, body)

proc main()
    n .= UInt64.fromString(getCMDArgument(1)[])[]
    bodies := bodies()
    offsetMomentum(bodies)
    energy(bodies).printLn()
    scaleBodies(bodies, dt())
    for i := 0; i <= n; i++
        advance(bodies)
    scaleBodies(bodies, recipDT())
    energy(bodies).printLn()


Мой компьютер: CPU Ryzen 2200G, RAM 16 Gb 2933 Mhz dual-chanel
Вот результаты:

Вариант программы Время исполнения (Сек.)
Не оптимизированная версия на Си. clang -lm -O1 -march=native 4,9
Не оптимизированная версия на Си. clang -lm -O2 -march=native 3,71
Не оптимизированная версия на Си. clang -lm -O3 -march=native 3,71
Оптимизированная версия на Си. clang -lm -O1 -march=native 4,14
Оптимизированная версия на Си. clang -lm -O2 -march=native 3,36
Оптимизированная версия на Си. clang -lm -O3 -march=native 2,48
Не оптимизированная версия на Си. gcc -lm -O1 -march=native 5,56
Не оптимизированная версия на Си. gcc -lm -O2 -march=native 3,55
Не оптимизированная версия на Си. gcc -lm -O3 -march=native 3,61
Оптимизированная версия на Си. gcc -lm -O1 -march=native 3,58
Оптимизированная версия на Си. gcc -lm -O2 -march=native 3,24
Оптимизированная версия на Си. gcc -lm -O3 -march=native 3,34
cine. clang -lm -O1 -march=native 9,02
cine. clang -lm -O2 -march=native 7,2
cine. clang -lm -O3 -march=native 7,13
cine. gcc -lm -O1 -march=native 10,53
cine. gcc -lm -O2 -march=native 6,51
cine. gcc -lm -O3 -march=native 6,32
Не оптимизированная версия на Rust. rustc -C opt-level=1 -C target-cpu=native -C lto -C codegen-units=1 15,1
Не оптимизированная версия на Rust. rustc -C opt-level=2 -C target-cpu=native -C lto -C codegen-units=1 4,87
Не оптимизированная версия на Rust. rustc -C opt-level=3 -C target-cpu=native -C lto -C codegen-units=1 4,66
Оптимизированная версия на Rust. rustc -C opt-level=1 -C target-cpu=native -C lto -C codegen-units=1 124,13
Оптимизированная версия на Rust. rustc -C opt-level=2 -C target-cpu=native -C lto -C codegen-units=1 3,31
Оптимизированная версия на Rust. rustc -C opt-level=3 -C target-cpu=native -C lto -C codegen-units=1 2,37
go 4,69
python -OO 423,6
pypy -OO 38,4

14 комментариев:

  1. Блин чувак, как же так?
    Ты хочешь выкинуть в жопу 12 лет своей работы?(

    ОтветитьУдалить
    Ответы
    1. Разработка и тестирование компилятора и стандартной библиотеке заняло меньше года, 12 лет - это прорабатывание идей и перебор различных вариантов, я в сумме уже штук 7 компиляторов написал. Я думаю что я теряю примерно пол года.

      Удалить
  2. PS в СИ тоже нету ООП и че?) Пишу на нем не парясь об этом.

    ОтветитьУдалить
    Ответы
    1. Да я не адепт ООП, просто оно позволит решить ряд проблем которые сейчас есть.

      Удалить
  3. Пожалуйста, не удаляйте блог и github репозиторий. Просто пометьте заметным образом о перезапуске проекта и развитии новых кодовой и идейной основ.

    ОтветитьУдалить
    Ответы
    1. github репозиторий я сам передумал удалять, а вот блог хотел удалять, но если нужен - оставлю.

      Удалить
  4. Здравствуйте. Есть какие-нибудь новости о проекте языка с 0?

    ОтветитьУдалить
    Ответы
    1. Готов компилятор (на go), написана почти вся стандартная библиотека, кроме реализации ассоциативных массивов и работы с ос (файлы, каталоги и тд). Сейчас достаточно сложная жизненная ситуация, если в жизни всё пойдёт более-менее нормально, то всё будет готово где то в конце февраля.

      Удалить
  5. Восхищаюсь вашим начинанием. Вы настоящий программист. Спасибо, что вдохновляете. Спасибо, что не всё ради бабок. Удачи!

    ОтветитьУдалить
  6. Вечное стремление к совершенству. Проект всей жизни не может быть закончен никогда. Работаешь программистом или так хобби о осталось?

    ОтветитьУдалить
    Ответы
    1. Вечное стремление к совершенству. Проект всей жизни не может быть закончен никогда.

      Так проекты которым 40 лет, всё равно развиваются и улучшаются, всегда есть что улучшить. Я уже переписываю компилятор версии 0.1 на своём языке, хотя уже сейчас есть куча наработок для версии 0.2 и 0.3.

      Работаешь программистом или так хобби о осталось?

      Не не работаю, но если бы работал, всё равно это было бы хобби.

      Удалить
  7. Здраствуйте!
    Я новичок, тут случайно оказался прочитав ваш пост на хабре:
    https://habr.com/ru/post/481276/
    Занимался изучением RUST и решил загуглить в поиск "в каких языках программирования впервые придуман слайс".
    Результат поиска выдал ваш пост.
    С удовольствием прочитал вашу статью. Восхищаюсь вами и желаю удачи, не бросайте!
    У меня к вам вопрос как знатоку "нижних этажей", понял что для меня ваше мнение важно.
    Мое желание изучать RUST построено на иррациональных основаниях. Слепой вере. Возможно я жертва рекламмы что RUST это какая-то мега крутая имба. Язык даст мне какие-то особые преимущества по сравнению с теми кто начал с С или С++, что в RUST я познаю лучшие идеи из мира программирования 21 века, а не пыльные концепции 60-х и 70-х место которым на свалке (по этой причине не стал учить C, С++. Косвенным подтвержденим верности своего выбора считаю рост популярности RUST. Мне достаждает мысль что я чем-то напоминаю футбольного фанатика слепого адепта). Признаюсь мне импонируют высокие зарплаты RUST-разработчиков, облизываюсь.
    Я бы хотел взгляд со стороны, обратную связь тому ли я посвящаю свое время. Во мне живет страсть к программированию и невежество, которое нужно срочно ликвидировать. У меня давнее желаение разобраться в каком-либо языке нижнего уровня. Это желание поедало мнея при знакомстве с Python.
    Изучение Python не удовлетворяло знакомством с кухней. Во мне усиливолось ощущения растения без корней. Некой отрезанности, изолированности от железа. Невежества. Только окунувшись в Rust я отметил полезным для себя знакомство со стеком, кучей, владельцами памяти, укзаателями.
    Изучая RUST всего неделю получил удовлетворение. Это для меня неожиданно.
    Я читаю и понимаю все о чем пишет автор книги RUST-бука и как ни страно хорошая книга и вызвала беспокойства. Я бы не хотел чтобы моя любовь к хорошей книге привела к ошибочному выбору плохого языка програмирования (RUST по вашему плохоя язык или хороший?
    Что можете сказать о моем выборе?)
    Не знаю что я хочу услышать. Наверно одобрение выбора. Возможно критику моего выбора и разрушение иллюзий. Возможно лучшего совета на что обратить внимание и на что потратить усилия чтобы стать мощным спецом, а не подражателем. Спасибо!

    P.s. В голове засел баян, что выбор языков нижнего уровня подходит людям дружащим с паяльником, ардунио, радиолюбителям...
    Как у вас с пояльником? Я переживаю о том что паять никогда не любил и не желаю даже начинать, соответсвенно байк утверждает что язык нижнего уровня мне подходит.

    ОтветитьУдалить

Пожалуйста без мата и оскорблений. Если хотите сообщить об ошибках, для этого есть форма обратной связи.