我正在编写一个助手类来评估网格上的参数化函数。由于网格不会随着参数的变化而变化,我选择将其作为类属性一次性创建。
然而,我意识到,与将网格作为全局变量相比,将网格作为类属性会导致性能显著下降。更有趣的是,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
如何解释这种性能差异?
我将网格从类属性移动到全局变量。我希望这个变化对性能是中性的。然而,性能发生了重大变化。