可以使用model = tf.function(model, jit_compile=True)启用XLA.通过这种方式,有些型号的速度更快,有些则更慢.到现在为止还好.

但为什么在某些情况下,model = tf.function(model, jit_compile=None)可以显著提高速度(没有TPU)?

jit_compile docs个州:

如果为None(默认),则在TPU上运行时使用XLA编译函数 并在上运行时通过常规函数执行路径 其他设备.

我在两台非TPU(甚至非GPU)机器(安装了最新的TensorFlow(2.13.0))上运行我的测试.

import timeit

import numpy as np
import tensorflow as tf

model_plain = tf.keras.applications.efficientnet_v2.EfficientNetV2S()
model_jit_compile_true = tf.function(tf.keras.applications.efficientnet_v2.EfficientNetV2S(), jit_compile=True)
model_jit_compile_false = tf.function(tf.keras.applications.efficientnet_v2.EfficientNetV2S(), jit_compile=False)
model_jit_compile_none = tf.function(tf.keras.applications.efficientnet_v2.EfficientNetV2S(), jit_compile=None)


def run(model):
    model(np.random.random(size=(1, 384, 384, 3)))


# warmup
run(model_plain)
run(model_jit_compile_true)
run(model_jit_compile_false)
run(model_jit_compile_none)

runs = 10
duration_plain = timeit.timeit(lambda: run(model_plain), number=runs) / runs
duration_jit_compile_true = timeit.timeit(lambda: run(model_jit_compile_true), number=runs) / runs
duration_jit_compile_false = timeit.timeit(lambda: run(model_jit_compile_false), number=runs) / runs
duration_jit_compile_none = timeit.timeit(lambda: run(model_jit_compile_none), number=runs) / runs

print(f"{duration_plain=}")
print(f"{duration_jit_compile_true=}")
print(f"{duration_jit_compile_false=}")
print(f"{duration_jit_compile_none=}")
duration_plain=0.53095479644835
duration_jit_compile_true=1.5860380740836262
duration_jit_compile_false=0.09831228516995907
duration_jit_compile_none=0.09407951850444078

推荐答案

但是,为什么在某些情况下,Model=tf.unction(Model,jit_Compile=None)可以显著提高速度(没有TPU)?

speedup is mainly due to the graph modeenabled by tf.function,比model_plain中使用的Eager 执行要快得多.

最重要的是,我们有secondary effects of XLA compilation with jit_compile flag个,但它们非常依赖于计算体系 struct .例如,在GPU加速器下编译时,这些数字看起来会有很大不同.

最后但并非最不重要的一点是,benchmarking methodology should be corrected to take into account variation在10次运行和所讨论的用例中确实是巨大的(否则,结果将是误导的,甚至是矛盾的,例如,由于高度变化,XLA=None平均看起来会更快). 为了将来参考,让我们明确一下,100 is inaccurate

# average runtime on 10 repetitions without variance is inaccurate
print("Eager conv:", timeit.timeit(lambda: conv_layer(image), number=10))

以下更正和扩展的代码片段,在带有GPU的Kaggle笔记本上执行,演示了improvements come mostly from the graph modeXLA compilation gives some further speedup.

import timeit

import numpy as np
import tensorflow as tf

model_plain = tf.keras.applications.efficientnet_v2.EfficientNetV2S()
model_tffunc = tf.function(tf.keras.applications.efficientnet_v2.EfficientNetV2S(), jit_compile=None)
model_jit_compile_true = tf.function(tf.keras.applications.efficientnet_v2.EfficientNetV2S(), jit_compile=True)
model_jit_compile_false = tf.function(tf.keras.applications.efficientnet_v2.EfficientNetV2S(), jit_compile=False)
model_jit_compile_none = tf.function(tf.keras.applications.efficientnet_v2.EfficientNetV2S(), jit_compile=None)

x = np.random.random(size=(1, 384, 384, 3))

def run(model):
    model(x)

# warmup
run(model_plain)
run(model_tffunc)
run(model_jit_compile_true)
run(model_jit_compile_false)
run(model_jit_compile_none)

# benchmarking
duration_plain = %timeit -o run(model_plain)
duration_tffunc = %timeit -o run(model_tffunc)
duration_jit_compile_true = %timeit -o run(model_jit_compile_true)
duration_jit_compile_false = %timeit -o run(model_jit_compile_false)
duration_jit_compile_none = %timeit -o run(model_jit_compile_none)

print(f"{str(duration_plain)=}")
print(f"{str(duration_tffunc)=}")
print(f"{str(duration_jit_compile_true)=}")
print(f"{str(duration_jit_compile_false)=}")
print(f"{str(duration_jit_compile_none)=}")

从统计上看,我们有:duration_plain > duration_jit_compile_false = duration_jit_compile_none = duration_tffunc > duration_jit_compile_true,从输出中可以看到:

369 ms ± 3.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
16.1 ms ± 2.13 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
11.6 ms ± 882 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
15.9 ms ± 508 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
15.5 ms ± 450 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
str(duration_plain)='369 ms ± 3.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)'
str(duration_tffunc)='16.1 ms ± 2.13 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)'
str(duration_jit_compile_true)='11.6 ms ± 882 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)'
str(duration_jit_compile_false)='15.9 ms ± 508 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)'
str(duration_jit_compile_none)='15.5 ms ± 450 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)'

完整的例子是,see this public notebook.

注:这种测量变化的方法是有用的,但是not fully accurate.

Python相关问答推荐

如何在Python中使用ijson解析SON期间检索文件位置?

请从Python访问kivy子部件的功能需要帮助

有条件地采样我的大型DF的最有效方法

如何在Python中使用io.BytesIO写入现有缓冲区?

仅从风格中获取 colored颜色 循环

更改键盘按钮进入'

如何使用数组的最小条目拆分数组

为什么抓取的HTML与浏览器判断的元素不同?

在pandas中使用group_by,但有条件

索引到 torch 张量,沿轴具有可变长度索引

导入错误:无法导入名称';操作';

交替字符串位置的正则表达式

用两个字符串构建回文

根据客户端是否正在传输响应来更改基于Flask的API的行为

如何在FastAPI中替换Pydantic的constr,以便在BaseModel之外使用?'

Python类型提示:对于一个可以迭代的变量,我应该使用什么?

提取数组每行的非零元素

Autocad使用pyautocad/comtypes将对象从一个图形复制到另一个图形

ModuleNotFoundError:Python中没有名为google的模块''

极柱内丢失类型信息""