我正在尝试使用Bokeh创建平滑的交互式可视化,以显示多维数组的不同切片。切片中的数据根据用户交互而变化,因此必须每秒更新多次。我编写了一个Bokeh应用程序,其中包含几个小图像绘图(64x64值),用于显示切片的内容,并使用回调函数在用户与应用程序交互时更新ColumnDataSources。一切都按预期工作,但我最多只能得到2或3帧每秒,我希望至少获得10帧。
这是我的代码简化样本,使用16个图像,并使用周期性回调每100ms模拟用户交互。在Mac和Linux上使用Bokeh 0.12.3和Python 2.7,两台机器的计时几乎完全相同(每帧约300ms)。
我已经尝试使用只有一个数据源,每个情节都有不同的字段,以及使用stream()方法更新数据(尽管这没有意义,因为整个图像都被替换了),但我没有获得任何性能收益。有人知道我该怎么做来改善这种可视化的交互性吗?我更新图像数据时做错了什么吗?
我猜想瓶颈是图像数据的JSON编码/解码引起的开销,可能会在未来得到改善,因为 Bokeh 的开发人员认识到了这个问题并尝试解决它。不幸的是,看起来修复的时间不会很快到来。
还有其他建议吗? https://github.com/bokeh/bokeh/issues/2204 https://github.com/bokeh/bokeh/pull/5429
这是我的代码简化样本,使用16个图像,并使用周期性回调每100ms模拟用户交互。在Mac和Linux上使用Bokeh 0.12.3和Python 2.7,两台机器的计时几乎完全相同(每帧约300ms)。
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/pull/5429