如何有效计算核/矩阵

问题描述 投票:0回答:1
import numpy as np

solution_point_count = 150
impedance_datapoint_count = 134 

impedance_frequency = np.logspace(np.log10(100000), np.log10(0.0199), impedance_datapoint_count)
solution_frequency_logspace = np.logspace(np.log10(100000), np.log10(0.06), solution_point_count)
    
# Initializing zeros matrix to store results     
Z_RC = np.zeros((impedance_datapoint_count,solution_point_count))

#Constructing Debye Model for RC Kernel
#Debye Model: Z_RC = 1/(1 + iω*𝜏) where ω = 2πf and 𝜏 = RC = 1/(2πf)

for n in range(solution_point_count):
    for m in range(impedance_datapoint_count):
        Equation = 1/(1+1j*impedance frequency[m]/solution_frequency_logspace[n])
            Z_RC[m,n] = np.real(Equation) # Extracting real part only

虽然这可以创建内核 Z_RC,但它非常慢并且可能效率低下。有没有更有效的方法来做到这一点?也许通过矢量化?

python-3.x numpy matrix optimization vectorization
1个回答
0
投票

最简单的解决方案是使用 :

from numba import njit

@njit
def calculate_numba(impedance_frequency, solution_frequency_logspace):
    solution_point_count = len(solution_frequency_logspace)
    impedance_datapoint_count = len(impedance_frequency)

    Z_RC = np.empty((impedance_datapoint_count, solution_point_count))

    for n in range(solution_point_count):
        for m in range(impedance_datapoint_count):
            Equation = 1 / (
                1 + 1j * impedance_frequency[m] / solution_frequency_logspace[n]
            )
            Z_RC[m, n] = np.real(Equation)  # Extracting real part only

    return Z_RC

使用

perfplot
进行基准测试:

import numpy as np
import perfplot
from numba import njit


def generate_impedance_frequency(solution_point_count, impedance_datapoint_count):
    impedance_frequency = np.logspace(
        np.log10(100000), np.log10(0.0199), impedance_datapoint_count
    )
    solution_frequency_logspace = np.logspace(
        np.log10(100000), np.log10(0.06), solution_point_count
    )
    return impedance_frequency, solution_frequency_logspace


def calculate_normal(impedance_frequency, solution_frequency_logspace):
    solution_point_count = len(solution_frequency_logspace)
    impedance_datapoint_count = len(impedance_frequency)

    Z_RC = np.empty((impedance_datapoint_count, solution_point_count))

    for n in range(solution_point_count):
        for m in range(impedance_datapoint_count):
            Equation = 1 / (
                1 + 1j * impedance_frequency[m] / solution_frequency_logspace[n]
            )
            Z_RC[m, n] = np.real(Equation)  # Extracting real part only

    return Z_RC


@njit
def calculate_numba(impedance_frequency, solution_frequency_logspace):
    solution_point_count = len(solution_frequency_logspace)
    impedance_datapoint_count = len(impedance_frequency)

    Z_RC = np.empty((impedance_datapoint_count, solution_point_count))

    for n in range(solution_point_count):
        for m in range(impedance_datapoint_count):
            Equation = 1 / (
                1 + 1j * impedance_frequency[m] / solution_frequency_logspace[n]
            )
            Z_RC[m, n] = np.real(Equation)  # Extracting real part only

    return Z_RC


# check if the calculation is the same:

solution_point_count = 150
impedance_datapoint_count = 134

impedance_frequency, solution_frequency_logspace = generate_impedance_frequency(
    solution_point_count, impedance_datapoint_count
)

out1 = calculate_normal(impedance_frequency, solution_frequency_logspace)
out2 = calculate_numba(impedance_frequency, solution_frequency_logspace)

assert np.allclose(out1, out2)


perfplot.show(
    setup=lambda n: generate_impedance_frequency(n, n),
    kernels=[
        calculate_normal,
        calculate_numba,
    ],
    labels=["normal", "numba"],
    n_range=[10, 20, 50, 100, 150, 200],
    xlabel="N x N",
    logx=True,
    logy=True,
)

结果:

© www.soinside.com 2019 - 2024. All rights reserved.