Pull to refresh
58
0
Alexander Kalinin @alec_kalinin

User

Send message
Мне было бы интересно поглядеть на реализацию. Со своей стороны я бы попробовал это реализовать на cython и numba, потом оценить насколько все это хорошо работает и насколько красивое решение получилось.
А вы не пробовали для этих целей использовать Numba. С простыми двойными циклами она должна справляться очень хорошо.
Спасибо, полезная статья!

В своих проектах после долгих размышлений я все-таки отказался от чистого Python API и использовал Boost.Python. Плюс там есть поддержка NumPy, что важно. Пока все работает стабильно.
Cython это правильный олдскульный вариант для ускорения Python кода. Но я давно всем рекомендую Numba.

Одним декоратором можно добиться такой же скорости, как и у Cython без всяких .pyx модулей и С-подобного языка. Вот рабочий код для факториала:

from numba import jit

@jit
def test(x):
    y = 1
    for i in range(1, x+1):
        y *= i
    return y
Ох… Много странного в JavaScript. Например, await не работает в .forEach. И таких мест, где разные концепции пересекаются со странными side эффектам, слишком много.
Оно следствие уверенности, что научные теории, как модели реальности, полностью и однозначно описывают ее. Это заблуждение. Пока таких теорий нет, и вероятно, в принципе не появятся в будущем… То есть не будет ситуации Теория == Реальность, и соответственно полной детерминации

Для меня вопрос стоит в другой плоскости. Применим ли в принципе научный метод для познания реальности? И вообще, что есть научное знание?

Научный метод предполагает следующие вещи:
1. Есть независимая от нас объективная реальность
2. Есть независимый исследователь со своей свободной волей
3. Есть метод, заключающийся в построении исследователем моделей реальности (теорий) и их верификации путем эксперимента

Я сомневаюсь в пункте 2, а именно в независимости исследователя со свободной волей. Любой исследователь с точки зрения физики, является точно такой же частью материи, точно также участвующий в физическом процессе. Грубо говоря физик, изучающий элементарные частицы, это элементарные частицы изучающие сами себя.

Возьмем ту же игру жизь, а именно фигуру планер. Упрощая, планер имеет два состояния «A» и «B». Состояние «A» порождает состояние «B», которое в свою очередь опять порождает состояние «A» но уже с некоторым продвижением вперед. Эта хорошая модель научного знания, где исследователь порождает модели, которые в свою очередь позволяют исследователям построить следующие модели. Но на самом деле мы просто имеем самоподдерживающийся детерминированный процесс бесконечной рекурсии где нет места для свободной воли.
Спасибо за ссылку, очень интересная информация.
Ну так в игре «жизнь» тоже могут возникать сложные конфигурации и колебания, но процесс остается полностью детерминированным и определяется только начальной конфигурацией.
Это зависит от контекста, кто я, какие у меня параметры, чем я управляю, какие у меня возможности. Если я понимаю кто я, в каком я состоянии нахожусь, что сейчас произойдёт, что произойдёт потом, я принимаю решения.

Современная физика ставит под сомнение сам факт, что вы вообще можете принимать какие-либо решения. В физической картине мира нет никого, кто-бы решал.

К примеру, вы захотели кинуть камень. Или оставить его на месте. Картина мира 1. Решение возникает именно в вас. Внешний наблюдатель не имеет возможности предсказать состояние камня, оно не определено, и зависит полностью от вашего решения. Эта картина соответствует наличию у вас свободной воли. Картина мира 2. Полетит или не полетит камень определяется только совокупностью состояний всех элементарных частиц. Внешний наблюдатель полностью знает, что будет в следующий момент времени. Вы ничего не решаете, а выступаете только безвольным инструментом реализации состояния вселенной в следующий момент времени. Грубо говоря, камень сам решает лететь, после чего вызывает в вас состояние желания его кинуть.

Мне нравится история про то, как работают птицы. Вообще птицы насколько красивые, настолько же довольно тупые. Летать тяжело, приходится на всем экономить. Птицы могут выполнять только один процесс. На два процесса мозгов уже не хватает. Поэтому, когда птица ест что-то с земли, она вокруг вообще ничего не замечает. В это время она становится очень уязвимой для наземных хищников. И что делать? Мозг то увеличить нельзя?

Эволюция придумала следующее элегантное решение. Птицы стали кормиться стаей по следующему алгоритму:
— каждая птица 8 раз глотает что-то с земли
— потом 2 раза смотрит вокруг, если что-то не нравится, кричит
— если слышит какой-то крик, сразу взлетает

Таким образом в каждый момент времени 20% птиц смотрят вокруг, что дает очень неплохой обзор. Эта оказалась очень эффективная стратегия. С точки зрения птицы ей сначала захотелось, и она приняла решение кушать, а потом захотелось подумать о вечном, и она приняла решение посмотреть вокруг. А для внешнего наблюдателя это поведение полностью определено и ничем не отличается от битвы AI ботов на демо арене. Полностью детерминированное поведение, не оставляющее вообще никакой свободы выбора.

С физической точки зрения человек ничем не отличается от такой же стаи птиц. То, что нам хочется и мы думаем, что принимаем какое-то решение, на самом деле просто полностью детерминированный физический процесс.
Хм… А как насчет Копенгагенской интерпретации, где есть такая загадочная вещь, как «измерение»? Да, волновая функция коллапсирует в случайное состояние, но как раз момент коллапса зависит от нашей воли. Хоть что-то. ;)
Если я не ошибаюсь, то в классической физике свободной воли нет вообще. Тут царит полный научный детерминизм. В классической физике состояние системы в момент времени t+1 полностью и однозначно зависит от состояния системы в момент времени t. И хотя из-за огромной размерности этой системы нам никогда все эти состояния не просчитать, самого факта определенности это не отменяет.

А поскольку человек является частью этой системы, все его возможные действия полностью определены начальным состоянием системы за долго до его появления.

Лаплас, который заложил основания методов математической физики, придерживался взглядов абсолютного детерминизма, поэтому придумал своего демона. Так что свободную волю нужно действительно искать на квантовом уровне, больше вроде негде.
Вообще, публикацию по Alpha Zero достаточно сильно критиковали. Основные замечания к статье: а) сравнивали со Stockfish достаточно старой версии, б) во многих играх у Stockfish отключали дебютную книгу, в) были вопросы к балансу вычислительных ресурсов, так как Stockfish работает на CPU, а Alpha Zero на GPU, г) в статье были приведено лишь небольшое количество сыгранных партий.

Чтобы разобраться, что на самом деле из себя представляют нейросетевые шахматные движки, был организован проект lczero.org. Это попытка сделать полностью открытый нейросетевой движок по принципам alpha zero.

И тут открылись очень интересные особенности. Во-первых, движок оказался на самом деле очень сильным. Сейчас он как раз обыгрывает Stockfish в суперфинале на TCEC: tcec.chessdom.com. Но во-вторых, у него открылось огромное количество слабых мест. Можно поглядеть примеры партий, где он просто не видит элементарных вещей. Например, концепцию «бешеной ладьи» он вообще пока не может понять.
Вспоминаются слова одного опытного менеджера: "… там когда выручка падала, кровати не двигали. Там сразу эээ… ассортимент меняли".

Откровенно говоря, одежда в H&M на самом деле хлам. И это единственно реальная причина. Но удивительно другое. Неужели так сложно сейчас делать достаточно качественную одежду и при этом быть прибыльной компанией?

Я сейчас в основном перешел на Lands' End.

Введение
Я был одним из тех, кто просил написать статью про переход с Python на Julia. Большое спасибо!


Прежде всего я хочу согласиться с автором статьи. Да, впихнуть невекторизуемые операции в NumPy порой очень непросто. Cython это страшно, а Numba это непредсказуемо. Именно поэтому я пару лет назад чуть не ушел с Python на что-то другое. Но в то время чего-то другого я не нашел, и остался на Python.


Сейчас я выступлю в роли защитника Python и все-таки продолжу утверждать, что будущее численных расчетов все-таки за Python


Улучшаем код на Python
Я взял код из статьи за основу и провел свои собственные тесты. Длина выборки N=10^6 элементов типа np.int32.


Тест 1. Чистый Python.


def get_longest_0(x):
    maxLen = 0
    currLen = 0

    for bit in x:
        if bit == 1:
            currLen += 1
        else:
            maxLen = max(maxLen, currLen)
            currLen = 0
    return max(maxLen, currLen)

Результаты: 3.167 s


ОК, это исходная точка.


Тест 2. Все-таки запихиваем все в NumPy
Автор статьи правильно начал рассуждать о том, что код можно векторизовать путем сдвига и вычитания. Но решил, что это не очень хорошее решение. Но я все-таки довел это способ до конца.


def get_longest_1(x):
    x_ext = np.hstack(([0], x, [0]))
    x_difs = np.diff(x_ext)
    lengths = np.where(x_difs < 0)[0] - np.where(x_difs > 0)[0]
    max_len = np.max(lengths)

    return max_len

Результаты: 0.189 s


Быстрее где-то в 16 раз.


Кроме скорости выполнения по мне так такой способ гораздо нагляднее, чем первый итерационный способ в цикле. Но для этого нужно сменить свой способ мышления. Нужно думать в векторизованном стиле. Даже скорее в стиле потокового вычислительного графа, где мы отделяем операции о данных. А для операций мы строим полусимвольный граф вычислений. Но об этом позднее.


Тест 3. И все-таки Numba
Код, как в Tecт 1, но всего одна аннотация.


@numba.jit
def get_longest_2(x):
    maxLen = 0
    currLen = 0

    for bit in x:\
    ...

и...


Результаты: 0.009 s


Еще раз в 20 быстрее, чем NumPy.


Да, Numba порой непредсказуема, но она очень активно развивается. И сейчас все больше случаев, где она просто хорошо работает.


Рассуждение о будущем научных вычислений
Язык Julia можно рассматривать как продолжение линии Fortran, где нам нужно написать числодробилку для каких-нибудь сеточных методов в таком императивном стиле, плюс распараллелить все по типу OpenMP. В этом смысле язык Julia идеален.


Но проблема то в том, что для современного железа это слишком низкий уровень, не позволяющий достичь максимальной производительности. Современное железно это многоядерные (реально многоядерные) процессоры со своими уровня кэша + GPU. Потоки данных между таким железом нужно гонять достаточно нетривиальным образом для максимальной производительности.


В стиле Fortran эффективный код для этого написать крайне нетривиально. И старый добрый LAPACK уже не справляется.


Современный ответ на эту проблему это концепция потоковых полусимвольный графов вычислений. Что-то типа TensorFlow. Мы отделяем граф вычислений от потоков данных. Граф вычислений собираем из готовых блоков, которые автоматически распределяются под разнообразное железо.


На мой взгляд Julia слишком низкоуровневая для этого. А вот Python подходит под эту концепцию на все 100%.


А теперь поглядим на Cython и Numba с этой точки зрения. В Numba один и тот же код можно автоматически распараллелить для мультиядерных CPU аннотацией '@numba.jit(nopython=True, parallel=True)', а при желании автоматически все отправить на GPU аннотацией '@cuda.jit'.


Проект, где Cython зашел идеально, это cupy. Это интерфейс NumPy, но реализованный полностью на GPU. Более того, они предлагают вообще писать гетерогенный код, который с точки исходного кода полностью одинаков, а проблемы как эффективно выполнить его на GPU полностью берет на себя CuPy.


CuPy один из лучших примеров, как нужно писать на Cython. Cython тут выступает таким клеем между Python и низкоуровневым GPU кодом. Например, вот тут
https://github.com/cupy/cupy/blob/master/cupy/cuda/cublas.pyx один из немногих случаев, когда я читал Cython код без головной боли.


Вот в рамках такой концепции мне Python кажется более прогрессивным языком, чем Julia. Хотя может быть я не очень знаю куда дальше собирается идти Julia.

Почему вдруг черт дёрнул писать на Julia и чем недостаточно было Python+numpy? Это вопрос на статью, если вдруг кому-то нереально интересно, то могу написать.

Поддерживаю, очень интересно!

Я сам долго мучался с проблемой выбора инструмента и все-таки остановился на Python. Да cython (местами уродливый), да numba (далеко не гарантия) и да, местами С. Но для моей задачи удалось очень хорошо локализовать эти критические места и аккуратно их спрятать за простой интерфейс. Зато на высоком уровне получилась сказка — просто, понятно и быстро за счет оптимизированного низкого уровня. Так получилось, что 70%-80% процентов активной разработки в моем проекте как раз было на верхнем уровне. В результате Python зашел просто идеально.

Но не всегда так бывает, конечно, поэтому очень интересно послушать мнение с другой стороны.
В MatLab все хорошо и красиво, когда решаешь стандартную задачу в рамках готового тулбокса. Но любой шаг в сторону превращается в большие мучения.

Для MatLab не сложилась индустрия развития платформы средствами сообщества. Это плохо. И нужно понимать, что сообщество это не только юные падаваны, но и вполне себе крутые профессора, которые пишут решения на пике технологий. И в последнее время это почти всегда python.

Вот к примеру расчет гравитационных волн от слияния черных дыр.
Не сказал бы, что Python удобнее MATLAB: например там, где в MATLAB можно написать что-то вроде sin(1:5) в Python придётся писать зубодробительные list comprehensions

Это не совсем верно, как раз NumPy и предоставляет удобную векторную нотацию, вот пример с sin

from numpy import sin, aranage

sin(arange(5))


А вот как раз пример матрично-векторных операций

import numpy as np
import numpy.linalg as la

n = 100
A = np.random.rand(n, n)
B = np.random.rand(n, n)
y = np.random.rand(n, 1)


# поэлементное умножение
C1 = A * B

# матричное произведение
C2 = A @ B

# решение СЛАУ с регуляризацией
E = np.eye(n)
x = la.inv(A.T @ A + E) @ A.T @ y


… тогда как для чего-то более серьёзного вроде авионики его никто в здравом уме использовать не станет.

Ну как сказать, если вбить в google 'aerospace python jobs' то количество вакансий от крупных компаний будет достаточно большим.
Ааа… Как можно пользоваться языком, у которого индексы массива начинаются с 1, а не с 0.

А если серьезно, Julia это такой MatLab на стероидах. Писать большие программы на MatLab это ад, да и стоит MatLab просто бешеных денег. Поэтому в сообществе разработчиков научного софта возникла идея написать аналог MatLab'а, но с более качественным внутренним языком и open source.

Для того времени идея была верной. Научные расчеты на Python были в самом зачаточном виде, особых альтернатив не было. Авторы Julia признавались, что если бы к тому времени был бы NumPy, они бы не стали писать Julia.

И их идея частично удалась. В основе Julia одно из лучших ядер линейной алгебры и очень хорошие средства параллелизации. Если бы не выстрелил Python, сейчас Julia была бы ведущим языком для научных расчетов.

Но Python выстрелил. Благодаря NumPy. NumPy, конечно, просто гениальный проект. Python + NumPy это идеальный компромис между силой языка общего назначения и удивительной гибкостью, позволяющей строить очень ясные математические операции.

Сейчас уже в Python перетянули все самые полезные вещи, в том числе и из Julia: cupy — работа на GPU с интерфейсом NumPy, numba — JIT компиляция для научных расчетов, parallel accelerator стянутая из Julia автоматическая параллелизация, всем известный Tensorflow, и т.п.

В общем, если человек приходит из мира MatLab, Julia лучший выбор. Но в целом и общем, научный Python это лучше что есть в мире научного программирования.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity