我正在尝试使用 Bokeh 创建多维数组的不同切片的平滑交互式可视化。切片中的数据根据用户交互而变化,因此每秒必须更新几次。我编写了一个 Bokeh 应用程序,其中包含几个小图像图(64x64 值)来显示切片的内容,以及在用户与应用程序交互时更新 ColumnDataSources 的回调。一切都按预期工作,但我每秒无法获得超过 2 或 3 帧,我希望至少获得 10 帧。
这是我的代码的简化示例,使用 16 个图像,每 100 毫秒定期回调一次来模拟用户交互。在 Mac 和 Linux 上使用 Bokeh 0.12.3 和 Python 2.7,我在两台机器上得到几乎完全相同的计时(每帧约 300 毫秒)。
from __future__ import print_function, division
from random import randint
from timeit import default_timer as timer
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
# Set up app and fake data
grid_size = 4
data_size = 64
names = ['d{}'.format(i) for i in range(grid_size)]
plots = [[None for _ in range(grid_size)] for _ in range(grid_size)]
sources = dict()
num_images = 16
image_data = [[np.random.rand(data_size, data_size)] for i in range(num_images)]
# Create plots and datasources
plot_size = 256
for row, row_name in enumerate(names):
for col, c_name in enumerate(names):
d_name = row_name + "_" + c_name
sources[d_name] = ColumnDataSource(
{'value': image_data[randint(0, num_images - 1)]})
plots[row][col] = figure(plot_width=plot_size,
plot_height=plot_size,
x_range=(0, data_size),
y_range=(0, data_size))
plots[row][col].image('value', source=sources[d_name],
x=0, y=0, dw=data_size, dh=data_size,
palette="Viridis256")
# Updates
def update():
global sources
start_update, end_update = [], []
start_time = timer()
for row, row_name in enumerate(names):
for col, c_name in enumerate(names):
d_name = row_name + "_" + c_name
new_data = dict()
new_data['value'] = image_data[randint(0, num_images - 1)]
start_update.append(timer()) # ----- TIMER ON
sources[d_name].data = new_data
end_update.append(timer()) # ----- TIMER OFF
print("\n---- \tTotal update time (secs): {:07.5f}".format(timer() - start_time))
print("+ \tSources update times (secs): {}".format(
["{:07.5f}".format(end_update[i] - s) for i,s in enumerate(start_update)]))
# Document
grid = gridplot(plots)
curdoc().add_root(grid)
curdoc().add_periodic_callback(update, 100)
我尝试过为每个图仅使用一个具有不同字段的数据源,并使用 Stream() 方法更新数据(尽管它没有意义,因为整个图像正在被替换),但我还没有实现任何目标性能增益。有谁知道我可以做些什么来提高此可视化的交互性?我更新图像数据时做错了什么吗?
我的猜测是,瓶颈是由图像数据的 JSON 编码/解码引起的开销,将来可能会有所改善,因为 Bokeh 开发人员似乎已经意识到这个问题并试图解决它。遗憾的是,修复似乎不会很快到来。
https://github.com/bokeh/bokeh/issues/2204 https://github.com/bokeh/bokeh/issues/2204
https://github.com/bokeh/bokeh/pull/5429 https://github.com/bokeh/bokeh/pull/5429
还有其他建议吗?