Ускорьте длинный код Python, который оказывается медленным только из-за одного блока - PullRequest
0 голосов
/ 31 октября 2019

У нас есть огромный объем в пространстве, заполненный множеством частиц (~ 10 ^ 8) с известным массивом масс ('HI_mass'), 3d-позициями ('HI_position') и некоторой интересной дробью ('HI_fraction'). В этом томе также есть несколько воображаемых сфер (~ 10 ^ 3) с различным, но известным массивом масс ('mass_data'), позиций ('position_data') и размеров ('radius_data').

Мыхотите сложить все газовые частицы (вносящие частичный вклад в газовую массу) в каждой воображаемой сфере, чтобы придумать «gas_mass» для каждой из воображаемых сфер, упомянутых выше. Как только у нас есть эта масса для каждой сферы, мы вычисляем некоторую величину, называемую «sigma_HI». Если эта величина выше некоторого порогового значения, то мы отслеживаем индивидуальную массу этой сферы в виде словаря {id: масса}, чтобы позже использовать ее для дальнейших вычислений. Третий блок - это вечный запуск в контексте всего кода, который очень длинный и не включен;Я скопировал только ту часть кода, которая оказалась медленной.

import numpy as np

enclosing_circles_gas = {}
#info of imaginary spheres where *_data are stored arrays based on some random (otherwise positive integer) ids
for id, position, radius, mass zip(id_data, position_data, radius_data, mass_data):  

    if (mass >= low_mass_cutoff):
        for i in np.where(HI_fraction > 0):                            # HI_fraction is a 1d array
            gas_mass = 0
            if (np.linalg.norm(HI_position[i] - position) <= radius):  # HI_position and position: 3d array of particles and single sphere vector
                gas_mass += HI_mass[i]*HI_fraction[i]                  # HI_mass and HI_fraction are 1d arrays of particles and their fractions
            if (gas_mass/mass >= 1.0e-6):
                enclosing_circles_gas[id] = float('{:.4f}'.format(mass))

Мой вопрос: как использовать C ++ для преобразования этого очень медленного блока в python, чтобы ускорить весь код?

Вещи, которые я пробовал: Изменение вложенного цикла в понимание списка (но это все еще медленно)

if (mass >= low_mass_cutoff):
        gas_mass = sum( HI_mass[i]*HI_fraction[i] for i in np.where(HI_fraction > 0)[0] if (np.linalg.norm(HI_position[i] - position) <= radius))
        if (gas_mass/mass >= 1.0e-6):
            enclosing_circles_gas[id] = float('{:.4f}'.format(mass))

1 Ответ

1 голос
/ 01 ноября 2019

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

import math

def trunc_digits(x, digits):
    d = math.log10(abs(x)) - digits
    d = int(math.ceil(d))
    d = math.pow(10, d)
    m = math.fmod(x, d)
    x = x - m
    return x

x = 9.87654321e-6
print (x, "->", trunc_digits(x, 4))
y = 9.87654321e6
print (y, "->", trunc_digits(y, 4))

a = -1.87654321e-6
print (a, "->", trunc_digits(a, 4))
b = -1.87654321e6
print (b, "->", trunc_digits(b, 4))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...