我尝试使用Bokeh创建一个多维数组的不同切片的平滑交互式可视化。切片中的数据根据用户交互而改变,因此必须每秒更新几次。我编写了一个带有几个小图像图(64x64值)的Bokeh应用程序来显示切片的内容,以及当用户与应用程序交互时更新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/pull/5429
还有其他建议吗?
答案 0 :(得分:0)
正如其他人所提到的,已经实现了一种有效的二进制阵列协议。所以答案是升级到最新版本。
为了完整性,这里是结果的比较。
使用0.12.3
(原始帖子中的版本 - 确保使用龙卷风< 4.5):
----总更新时间(秒):0.14389 +来源更新时间(秒):['0.00943','0.00962','0.01100','0.00908','0.00004','0.00975','0.00984','0.00997','0.00946','0.00926',' 0.00912','0.00898','0.00900','0.00908','0.00999','0.01014'] ^ C
使用0.12.13
(截至此时的最新版本):
----总更新时间(秒):0.01999 +来源更新时间(秒):['0.00157','0.00231','0.00131','0.00143','0.00114','0.00123','0.00109','0.00118','0.00116','0.00102',' 0.00113','0.00118','0.00099','0.00099','0.00104','0.00104']
如果所有图像都存储在单个ColumnDataSource
的不同(长度1)列中并且一次更新,而不是迭代几个不同的数据源,则可能会有更多的边际改进。