我想通过 importScripts() 在 webWorker 中导入 2 个脚本,如下所示,但导入失败。如何处理?
self.importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs');
self.importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter');
我想通过 importScripts() 在 webWorker 中导入 2 个脚本,如下所示,但导入失败。如何处理?
self.importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs');
self.importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter');
目前,无法在 web-worker 上使用 webgl 实现,offlineCanvas 是一个实验性功能。但是,可以使用 CPU 后端。
这是委托给网络工作者执行计算的示例
<head>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.2/dist/tf.min.js"></script>
<script>
const worker_function = () => {
onmessage = () => {
console.log('from web worker')
this.window = this
importScripts('https://cdn.jsdelivr.net/npm/setimmediate@1.0.5/setImmediate.min.js')
importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.10.3')
tf.setBackend('cpu')
const res = tf.zeros([1, 2]).add(tf.ones([1, 2]))
res.print()
postMessage({res: res.dataSync(), shape: res.shape})
};
}
if (window != self)
worker_function();
</script>
<script>
const worker = new Worker(URL.createObjectURL(new Blob(["(" + worker_function.toString() + ")()"], { type: 'text/javascript' })));
worker.postMessage({});
worker.onmessage = (message) => {
console.log('from main thread')
const {data} = message
tf.tensor(data.res, data.shape).print()
}
</script>
</head>
使用张量,主线程和 Web Worker 之间共享的数据可能很大。此数据被克隆或传输。
不同之处在于,如果数据被克隆,Web Worker 仍会保留一份数据副本以供进一步处理。转移时,数据的所有权也会转移。与克隆相比,它的优点是传输速度快,实际上它可以看作是对引用的传递(如果来自带有指针的语言背景)
让我们用这两个片段来讨论性能
<head>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.2/dist/tf.min.js"></script>
<script>
const worker_function = () => {
onmessage = () => {
console.log('from web worker')
this.window = this
importScripts('https://cdn.jsdelivr.net/npm/setimmediate@1.0.5/setImmediate.min.js')
importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.10.3')
tf.setBackend('cpu')
const res = tf.randomNormal([2000, 2000, 3])
const t0 = performance.now()
postMessage({res: res.dataSync().buffer, shape: res.shape}, [res.dataSync().buffer])
console.log(`Prediction took ${(performance.now() - t0).toFixed(1)} ms`)
};
}
if (window != self)
worker_function();
</script>
<script>
const worker = new Worker(URL.createObjectURL(new Blob(["(" + worker_function.toString() + ")()"], { type: 'text/javascript' })));
worker.postMessage({});
worker.onmessage = (message) => {
console.log('from main thread')
const {data} = message
tf.tensor(new Float32Array(message.data.res), message.data.shape)
}
</script>
</head>
<head>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.2/dist/tf.min.js"></script>
<script>
const worker_function = () => {
onmessage = () => {
console.log('from web worker')
this.window = this
importScripts('https://cdn.jsdelivr.net/npm/setimmediate@1.0.5/setImmediate.min.js')
importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.10.3')
tf.setBackend('cpu')
const res = tf.randomNormal([2000, 2000, 3])
const t0 = performance.now()
postMessage({res: res.dataSync(), shape: res.shape})
console.log(`Prediction took ${(performance.now() - t0).toFixed(1)} ms`)
};
}
if (window != self)
worker_function();
</script>
<script>
const worker = new Worker(URL.createObjectURL(new Blob(["(" + worker_function.toString() + ")()"], { type: 'text/javascript' })));
worker.postMessage({});
worker.onmessage = (message) => {
console.log('from main thread')
const {data} = message
tf.tensor(message.data.res, message.data.shape)
}
</script>
</head>
我们可以看到两个片段之间的差异约为 10 毫秒。当以性能为代价时,如果必须克隆或传输数据,则需要考虑如何共享数据。
TensorflowJS 需要画布来进行 GPU 计算,而工作人员目前没有画布。
OffscreenCanvas 是一项正在开发的功能,但在 TFJS 使用它之前,它可能需要足够广泛的浏览器支持。