@shstkv_a

Прирост в производительности после переноса алгоритма с Python на C++/C?

Здравствуйте. В Пайтоне сейчас используются примерно такие блоки кода:
Для парсинга строк:
content = contents(rcsb)
    atoms = []
    for line in content:
        if line[0] == 'ATOM':
            atom = [list(map(int, line[1:2])), line[2], line[3], line[5], line[8],
                    list(map(float, line[10:13])), ]
            atoms.append(atom)
    return atoms

Для вычислений:
x2, y2, z2 = sympy.symbols('x y z', real=True)
            eq2 = sympy.Eq((x2 - x0) ** 2 + (y2 - y0) ** 2, atom00 ** 2 - (z2 - z0) ** 2)
            eq3 = sympy.Eq((x2 - x1) ** 2 + (y2 - y1) ** 2, atom11 ** 2 - (z2 - z1) ** 2)
            eq4 = sympy.Eq(z2, (z0 + z1) / 2)

            answer1 = sympy.solve([eq2, eq3, eq4])
            answer0 = []
            for q in answer1[1:2]:
                for k, i in q.items():
                    if k == x2:
                        answer0.append(i)

                    if k == y2:
                        answer0.append(i)

                    if k == z2:
                        answer0.append(i)

            V1 = sympy.Matrix([x1, y1, z1])
            E = sympy.Matrix([(x0 - x1) / length, (y0 - y1) / length, (z0 - z1) / length])
            if len(answer0) > 1:
                A = sympy.Matrix([answer0[0] - x1, answer0[1] - y1, answer0[2] - z1])
                x, y, z = E[0], E[1], E[2]
                coordinates = []
                i = 1
                while i <= precision: 
                    t = (2 * math.pi / precision) * i
                    M = sympy.Matrix(
                        [[(math.cos(t) + (1 - math.cos(t)) * x ** 2), ((1 - math.cos(t)) * x * y - math.sin(t) * z),
                          ((1 - math.cos(t)) * x * z + math.sin(t) * y)],
                         [((1 - math.cos(t)) * x * y + math.sin(t) * z), (math.cos(t) + (1 - math.cos(t)) * y ** 2),
                          ((1 - math.cos(t)) * y * z - math.sin(t) * x)],
                         [((1 - math.cos(t)) * x * z - math.sin(t) * y), ((1 - math.cos(t)) * y * z + math.sin(t) * x),
                          (math.cos(t) + (1 - math.cos(t)) * z ** 2)]])
                    coord_sympy = M * A + V1
                    xa, ya, za = float(coord_sympy[0]), float(coord_sympy[1]), float(coord_sympy[2])
                    coordinate = [xa, ya, za]
                    coordinates.append(coordinate)
                    i += 1

Еще есть перемножение матриц, умножение векторов, сложение и вычитание.
Код в вычислении матрицы поворота у меня занимает 0.6-0.9 секунд, а текст парсится практически мгновенно на пайтоне. Активно используется динамическая типизация, списки, словари и функции с 8-12 параметрами. Время работы алгоритма 26-28 минут. Хочется быстрее. С другими языками программирования (ЯП) не работал.
Вопросы:
Какой ЯП выбрать для изучения и на какие его разделы уделить внимание, чтобы перенести код программы как можно быстрее (в течение года)? Во сколько раз ожидать прироста в производительности работы алгоритма? Планируется, чтобы будущая приложение работало на сервере - ЯП важен? Или может библиотеку другую?
Спасибо за внимание.
  • Вопрос задан
  • 347 просмотров
Решения вопроса 2
@Everything_is_bad
Хочется быстрее.
начни с поиска узких мест и их оптимизации, так же можно попробовать pypy, после этого стоит рассмотреть cython

Какой ЯП выбрать для изучения
любой популярный компилируемый

Во сколько раз ожидать прироста в производительности работы алгоритма
неизвестно, в активных вычислениях может быть на порядок, но так же всегда можно написать кривую реализацию и только всё замедлить
Ответ написан
Vindicar
@Vindicar
RTFM!
У тебя вычисление повторяется для каждой строки? Посмотри, можно ли распараллелить код на несколько процессов (именно процессов, не потоков).
Также посмотри насчёт использования numpy/scipy и их численных солверов для систем уравнений вместо sympy. Может, используя sympy, получится сформулировать алгоритм расчёта, а уже его портировать на numpy?

Если надумаешь использовать numpy, держи в уме вот что: по возможности выполняй операции сразу над массивами значений. Упрощённо, вот это
a = numpy.array([3] * 1000000, dtype=numpy.float32)
b = 2 * a + 3

будет намного быстрее, чем это:
a = numpy.array([3] * 1000000, dtype=numpy.float32)
b = numpy.zeros_like(a)
for i in range(a.shape[0]):
    b[i] = 2 * a[i] + 3

Причина простая - операции над массивами реализуют перебор элементов массива нативно, т.е. с той же проивзодительностью, что и C/C++/Fortran. А вот сугубо питоньи циклы - штука медленная.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы