我正在编写一个帮助类来计算网格上的参数化函数.由于网格不会随参数而改变,所以我 Select 将其创建为一个class属性.

然而,我意识到,与将网格作为全局变量相比,将其作为class属性会导致显著的性能下降.更有趣的是,2D网格的性能差异似乎在1D网格中消失了.

以下是一个最低限度的"工作"例子,说明了这个问题:

import numpy as np
import time


grid_1d_size = 25000000
grid_2d_size = 5000
x_min, x_max = 0, np.pi / 2
y_min, y_max = -np.pi / 4, np.pi / 4

# Grid evaluation (2D) with grid as class attribute

class GridEvaluation2DWithAttribute:
    def __init__(self):
        self.x_2d_values = np.linspace(x_min, x_max, grid_2d_size, dtype=np.float128)
        self.y_2d_values = np.linspace(y_min, y_max, grid_2d_size, dtype=np.float128)

    def grid_evaluate(self):
        cost_values = np.cos(self.x_2d_values[:, None] * self.y_2d_values[None, :])
        return cost_values

grid_eval_2d_attribute = GridEvaluation2DWithAttribute()
initial_time = time.process_time()
grid_eval_2d_attribute.grid_evaluate()
final_time = time.process_time()
print(f"2d grid, with grid as class attribute: {final_time - initial_time} seconds")

# Grid evaluation (1D) with grid as global variable

x_2d_values = np.linspace(x_min, x_max, grid_2d_size)
y_2d_values = np.linspace(y_min, y_max, grid_2d_size)

class GridEvaluation2DWithGlobal:
    def __init__(self):
        pass

    def grid_evaluate(self):
        cost_values = np.cos(x_2d_values[:, None] * y_2d_values[None, :])
        return cost_values

grid_eval_2d_global = GridEvaluation2DWithGlobal()
initial_time = time.process_time()
grid_eval_2d_global.grid_evaluate()
final_time = time.process_time()
print(f"2d grid, with grid as global variable: {final_time - initial_time} seconds")

# Grid evaluation (1D) with grid as class attribute

class GridEvaluation1DWithAttribute:
    def __init__(self):
        self.x_1d_values = np.linspace(x_min, x_max, grid_1d_size, dtype=np.float128)

    def grid_evaluate(self):
        cost_values = np.cos(self.x_1d_values)
        return cost_values

grid_eval_1d_attribute = GridEvaluation1DWithAttribute()
initial_time = time.process_time()
grid_eval_1d_attribute.grid_evaluate()
final_time = time.process_time()
print(f"1d grid, with grid as class attribute: {final_time - initial_time} seconds")

# Grid evaluation (1D) with grid as global variable

x_1d_values = np.linspace(x_min, x_max, grid_1d_size, dtype=np.float128)

class GridEvaluation1DWithGlobal:
    def __init__(self):
        pass

    def grid_evaluate(self):
        cost_values = np.cos(x_1d_values)
        return cost_values

grid_eval_1d_global = GridEvaluation1DWithGlobal()
initial_time = time.process_time()
grid_eval_1d_global.grid_evaluate()
final_time = time.process_time()
print(f"1d grid, with grid as global variable: {final_time - initial_time} seconds")

这是我得到的输出:

2d grid, with grid as class attribute: 0.8012442529999999 seconds
2d grid, with grid as global variable: 0.20206781899999982 seconds
1d grid, with grid as class attribute: 2.0631387639999996 seconds
1d grid, with grid as global variable: 2.136266148 seconds

如何解释这种性能差异?

我将网格从class属性移动到全局变量.我认为这一变化对性能是中性的.然而,业绩出现了重大变化.

推荐答案

您不同意设置网格的数据类型.

比较

self.x_2d_values = np.linspace(x_min, x_max, grid_2d_size, dtype=np.float128)
self.y_2d_values = np.linspace(y_min, y_max, grid_2d_size, dtype=np.float128)

与:

x_2d_values = np.linspace(x_min, x_max, grid_2d_size)
y_2d_values = np.linspace(y_min, y_max, grid_2d_size)

如果未指定,默认类型为np.float32,比np.float128短4倍,通常快4倍,与您测量的时间相匹配.

Python相关问答推荐

如何在BeautifulSoup中链接Find()方法并处理无?

Python在tuple上操作不会通过整个单词匹配

点到面的Y距离

Gekko:Spring-Mass系统的参数识别

带条件计算最小值

2D空间中的反旋算法

更改键盘按钮进入'

如何在Python数据框架中加速序列的符号化

pyscript中的压痕问题

如何在WSL2中更新Python到最新版本(3.12.2)?

将9个3x3矩阵按特定顺序排列成9x9矩阵

SQLAlchemy Like ALL ORM analog

在vscode上使用Python虚拟环境时((env))

如何根据一列的值有条件地 Select 前N个组,然后按两列分组?

Tkinter菜单自发添加额外项目

pandas:在操作pandora之后将pandora列转换为int

Pandas在rame中在组内洗牌行,保持相对组的顺序不变,

如何获得满足掩码条件的第一行的索引?

类型对象';敌人';没有属性';损害';

如何在不遇到IndexError的情况下将基数10的整数转换为基数80?