GPU压力测试篇- TensorFlow

简介

该文档介绍使用Tensorflow框架,测试 NVIDIA 驱动的常见python 代码。

环境信息

编号

软件

软件版本

备注

01

驱动

470.57.02

02

cuda 版本

11.2

03

cudnn 版本

8.1.1.33

04

tensorflow

2.6

功能测试代码:

import tensorflow as tf
with tf.device('/CPU:1'):a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])c = tf.matmul(a, b)
print(c)

GPU 压力测试代码:

# On Titan X (Pascal)
# 8192 x 8192 matmul took: 0.10 sec, 11304.59 G ops/sec
# http://stackoverflow.com/questions/41804380/testing-gpu-with-tensorflow-matrix-multiplicationimport os
import sys
import tensorflow as tf
import time
import timeit
import datetimen=1000000000 #10亿次
dtype = tf.float32
with tf.device("/gpu:0"):matrix1 = tf.Variable(tf.ones((1, n), dtype=dtype))matrix2 = tf.Variable(tf.ones((n, 1), dtype=dtype))def gpu_run():with tf.device("/gpu:0"):product = tf.matmul(matrix1, matrix2)return productprint("开始计算:", time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))
gpu_time = timeit.timeit(gpu_run, number=1000)
print("计算结束:", time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))

CPU/GPU 压测比较代码:

# 屏蔽tensorflow输出的log信息
# 注意:代码在import tensorflow之前
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"import sys
print("python的版本信息:",sys.version)
#python的版本信息: 3.7.9 (default, Aug 31 2020, 17:10:11) [MSC v.1916 64 bit (AMD64)]import tensorflow as tf'''
验证GPU相对于CPU,在并行计算优势明显
'''
n=100000000 #1亿次# 创建在 CPU 环境上运算的 2 个矩阵
with tf.device('/cpu:0'):cpu_a = tf.random.normal([1, n])cpu_b = tf.random.normal([n, 1])print(cpu_a.device, cpu_b.device)# 创建使用 GPU 环境运算的 2 个矩阵
with tf.device('/gpu:0'):gpu_a = tf.random.normal([1, n])gpu_b = tf.random.normal([n, 1])print(gpu_a.device, gpu_b.device)import timeitdef cpu_run(): # CPU 运算函数with tf.device('/cpu:0'):c = tf.matmul(cpu_a, cpu_b)return cdef gpu_run():# GPU 运算函数with tf.device('/gpu:0'):c = tf.matmul(gpu_a, gpu_b)return c# 第一次计算需要热身,避免将初始化时间结算在内
cpu_time = timeit.timeit(cpu_run, number=100)
gpu_time = timeit.timeit(gpu_run, number=100)
print('首先计算10次(含热身环境)的平均时间,CPU计算消耗时间:%.3fms,GPU计算消耗时间:%.3fms!'%(cpu_time*1000, gpu_time*1000) )#正式计算10次,取平均时间
cpu1_time = timeit.timeit(cpu_run, number=10)
gpu1_time = timeit.timeit(gpu_run, number=10)print('正式计算10次的平均时间,CPU计算消耗时间:%.3fms,GPU计算消耗时间:%.3fms!'%(cpu1_time*1000, gpu1_time*1000))

压测

编号

先卡类型

显卡架构

计算时间

cuda 版本

TF版本

算力使用率

备注

01

P40-22G

帕斯卡

17秒

10.1

2.3

100%

x86_64

02

T4-16G

图灵

15秒

11.2

2.6

100%

x86_64

03

V100-32G

沃尔塔

7秒

10.1

2.3

100%

x86_64

04

A10-24G

安培

10秒

11.2

2.6

100%

x86_64

05

A100-40G

安培

6秒

11.2

2.6

100%

x86_64

1. 背景目的

对现有gpu的性能没有相关的测试,需要进行摸底测试

预期测试目的:

  • 完成gpu对训练及预测服务的性能测试

  • 对现场部署及使用提供支持

2. 测试环境

OS:Centos7
Linux kernel:Linux 3.10.0-1160.90.1.el7.x86_64
Docker Version:1.13.1
Docker Image:nvcr.io/nvidia/tensorflow:23.03-tf1-py3 (V1.15版本)

Docker OS:Ubuntu 20.04.5 LTS
Nvidia GPU Version:NVIDIA-SMI 470.161.03
CUDA Version: 12.1
TensorFlow Version:1.15.1
python Version:3.8.10

3. 测试方案

3.1、训练性能测试方案

  • 训练文件来源:GitHub - tensorflow/benchmarks: A benchmark framework for Tensorflow

  • 训练模型:resnet50

  • 训练数据集:全量imagenet数据,总大小约150G,图片张数超过1400w

  • 测试步骤:

    • 将全量的已转换为tfrecord格式的imagenet数据上传至存储卷下

    • 创建3个notebook任务,资源配置如下:

CPU

GPU

memory

6

0.5

20G

6

1

20G

12

2

40G

  • 上传tf_cnn_benchmark代码
  • 运行测试指令:python tf_cnn_benchmarks.py --model=resnet50 --num_gpus=${NUM_GPUS} --batch_size=32 --variable_update=parameter_server --data_dir=${DATA_DIR} --num_epochs=2

${DATA_DIR}为训练数据集文件train目录的路径
${NUM_GPUS}为当前notebook任务申请的GPU数量

2. 预测性能测试方案:

  • 预测服务模型:TensorFlow-Resnet50 v1,SavedModel格式

  • 模型来源:https://tfhub.dev/tensorflow/resnet_50/classification/1

  • 发压工具:

    • 下载

    • 说明:封装locust的性能测试工具,支持模型预测的性能测试。

  • 测试步骤:

    • 模型中心导入TensorFlow-Resnet50

    • 创建模型对应服务,资源配置如下:

CPU

GPU

MEMORY

4

0.5

8G

4

1

8G

8

2

16G

  • 创建相关应用
    • 利用发压工具对服务接口持续发压,观察压力测试结果及压测期间gpu显存使用情况及gpu使用率

一、GPU性能测试数据报告如下

1 需求背景

使用性能评估对服务终端进行压力测试,评估服务端性能,有助于定位性能瓶颈。

由于全量版本过多,高优测试一轮每个框架的最新版本,模型性能。

2. 测试方案

2.1 模型预测配置

  1. 每个副本 默认资源配置

    1. 副本数:1

    2. CPU:4

    3. 内存:8GB / 8192MB

    4. GPU:

      1. 仅用CPU的模型预测:0

      2. 依赖GPU(或必须使用GPU才能发挥性能的模型预测 :TensorFlow、Pytorch、Paddle):1

    5. GPU类型:Tesla-T4

注意

当测试时,发现服务的资源配置成为性能瓶颈时,应适当改大资源,否则无法测试出最大的性能数据。

2.2 模型选择

模型类型

镜像名称:镜像tag

是否使用GPU

模型类型

其他说明

Sklearn-v0.20

infsms-sklearn0.20.2

e0828eb1d118

modelserver

-

GBDT-v1.2.0

infsms-xgboost1.2.0

d09b82ae7baa

modelserver

服务需要设置环境变量:

OMP_NUM_THREADS:1

(NUM_WORKERS建议设置,本次测试没有设置此参数)

H2O-v3.26.0.5

infsms-h2o3.26.0.5

929fa6a953d1

modelserver

-

R-3.5.2

infsms-r3.5.2

64ff114623cb

modelserver

多并发请求成功率全部低于30

PMML

infsms-pmml0.9.11

d0276f6c47d9

modelserver

多并发请求成功率全部低于50

TensorFlow-v2.6.0

infsms-tensorflow2.6.0-cuda11.2-cudnn8

e88ef44c5251

modelserver

-

paddle-2.1

infsms-paddle2.1.0-cuda10.1-cudnn7

683ef1373304

modelserver

-

PyTorch-v1.10.1

infsms-pytorch1.10.0-cuda10.2-cudnn7

8812b855b620

modelserver

-

OONX-1.8

infsms-onnx1.3.0-cuda10.1-cudnn7

9840c6d7a900

modelserver

模型起预测onnx框架image信息匹配的不对

2.3 性能指标说明

  1. 最大并发:长时间压测下,预测服务能承受的稳定无异常的最大并发数。

  2. 最大TPS:长时间压测下,预测服务能达到的最大TPS

  3. 资源使用率:

    1. 包括CPU使用率、GPU算力平均使用率、GPU显存平均使用率、内存使用率

    2. 来自前端页面 用户可见的副本监控数据(获取自性能评估报告、 Prometheus监控数据)

    3. 仅列出压测过程中 采样到的最大占用率

3 模型预测性能

3.1 GBDT-v1.2.0模型预测

性能指标

pod性能数据

1个并发

中间数据

最大并发

中间数据

中间数据

中间数据

中间数据

单副本资源数

4/0/8G

4/0/8G

4/0/8G

4/0/8G

4/0/8G

4/0/8G

4/0/8G

Users(并发数)

1

30

50

100

300

500

1000

递增速率(VU/s)

1

2

5

10

20

35

66

发压时间

30min

30min

30min

30min

30min

30min

30min

发送请求数

537930

1406038

1408861

1405880

814857

822581

873953

req/s(QPS)

299.02

782.87

784.44

782.78

452.95

457.24

485.8

failures(整体失败率)

0

0

0

0

0.68%

1.64%

3.61%

failures/s

0

0

0

0

3.08

7.49

17.5

响应时间(最大)

75

77

119

1311

91852

91792

92606

响应时间(最小)

2

2

2

6

5

8

18

响应时间(中位数)

3

38

63

130

140

140

140

响应时间(平均值)

2.97

37.62

64.03

126.88

664.91

1184.59

2365.61

响应时间 latency 95%

3

40

67

130

270

290

3400

响应时间 latency 99%

4

42

69

140

7200

59000

61000

CPU使用率

20%

53%

53.06%

53.12%

46%->32%

40%->34%

35%

内存使用率

2.34%

2.34%

2.35%

2.37%

2.46%

2.65%

3.19%

分析说明:

  1. 最大并发为100

  2. 30min发压时间的平均QPS 最大是784.44左右

  3. 并发达到50后,QPS基本稳定,超过100并发时,开始出现报错:报错基本集中在发压后几分钟内,几分钟后请求成功率逐步上升,趋势图如下

3.2 Sklearn-v0.20 模型预测

性能指标

pod性能数据

1个并发

中间数据

最大并发

中间数据

单副本资源数

4/0/8G

4/0/8G

4/0/8G

4/0/8G

Users(并发数)

1

50

100

300

递增速率(VU/s)

1

5

10

20

发压时间

30min

30min

30min

30min

发送请求数

450442

1255059

1260003

690064

req/s(TPS)

250.38

697.64

700.39

383.58

failures(整体失败率)

0

0

0

0.86%

failures/s

0

0

0

3.29

响应时间(最大)

1046

1078

1343

91855

响应时间(最小)

2

3

5

15

响应时间(中位数)

3

70

140

150

响应时间(平均值)

3.07

70.3

141.36

772.63

响应时间 latency 95%

3

77

160

1100

响应时间 latency 99%

5

83

160

12000

CPU使用率

19%

54.27%

54.33%

54%->34%

内存使用率

1.95%

2%

2.02%

2.15%

分析说明

  1. 最大并发为200

  2. 30min发压时间的平均TPS 最大是700.39左右

  3. 并发达到100后,TPS 基本稳定,超过100并发时,开始出现报错。

3.3 H2O-V3.26.5模型预测

性能指标

pod性能数据

1个并发

最大并发

中间数据

中间数据

中间数据

中间数据

单副本资源数

4/0/8G

4/0/8G

4/0/8G

4/0/8G

4/0/8G

4/0/8G

Users(并发数)

1

50

100

300

500

1000

递增速率(VU/s)

1

5

10

20

35

66

发压时间

30min

30min

30min

30min

30min

30min

发送请求数

29799

28356

10579

11883

18374

36941

req/s(TPS)

16.59

15.79

5.9

6.62

10.24

20.59

failures(整体失败率)

0

0

0.59

66.66

75.15

99.91

响应时间(最大)

1671

6552

61043

92294

92502

61352.15

响应时间(最小)

33

102

1963

21743

21946

26621

响应时间(中位数)

57

3100

8300

60000

60000

61000

响应时间(平均值)

59.57

3166

17643

55670

61223.9

61352.15

响应时间 latency 95%

80

3900

38000

67000

78000

85000

响应时间 latency 99%

94

4800

58000

92000

92000

92000

CPU使用率

50%

76.43%

91.5%

92.5%

94.14%

94.56%

内存使用率

20%

33.34%

35.09%

35.62%

36.14%

37.18%

分析说明

  1. 最大并发为50

  2. 30min发压时间的平均TPS 最大是16.59左右

  3. 并发超过50时,开始出现报错。

3.4 Paddle-v2.1模型预测

性能指标

pod性能数据

1个并发

最大并发

中间数据

中间数据

中间数据

中间数据

单副本资源数

4/1/8G

4/1/8G

4/1/8G

4/1/8G

4/1/8G

4/1/8G

Users(并发数)

1

50

100

300

500

1000

递增速率(VU/s)

1

5

10

20

35

66

发压时间

30min

30min

30min

30min

30min

30min

发送请求数

20305

50549

50534

46758

57051

81977

req/s(TPS)

11.29

28.1

28.14

26.03

31.77

45.64

failures(整体失败率)

0

0

0.37

16.19

31.11

51.93

响应时间(最大)

1366

3977

62301

92458

91758

109176

响应时间(最小)

33

147

531

101

59

1

响应时间(中位数)

83

1800

3500

3600

4700

7500

响应时间(平均值)

79.65

1768.93

3592.37

12314.43

17432.58

26336.36

响应时间 latency 95%

87

1800

3600

60000

60000

61000

响应时间 latency 99%

90

1800

3600

67000

68000

68000

CPU使用率

11.73

26.80

26.42

26.42

26.34

23.13

内存使用率

21.39

21.42

21.46

21.60

22.11

22.79

AI加速卡算力平均使用率

21.30

16.64

后期是0

17.22

中途有使用率为0的一段

72.27

59.12

58.96

AI加速卡显存平均使用率

5.94

5.94

5.94

5.94

5.94

5.94

分析说明

  1. 最大并发为50

  2. 30min发压时间的平均TPS 最大是28.1左右

  3. 并发超过50时,开始出现报错。 加速卡算力平均使用率存在0的情况。

3.5 Tensorflow-v2.6模型预测

性能指标

pod性能数据

1个并发

中间数据

最大并发

中间数据

中间数据

中间数据

单副本资源数

4/1/8G

4/1/8G

4/1/8G

4/1/8G

4/1/8G

4/1/8G

Users(并发数)

1

50

100

300

500

1000

递增速率(VU/s)

1

5

10

20

35

66

发压时间

30min

30min

30min

30min

30min

30min

发送请求数

20992

78283

76802

65464

78072

103178

req/s(TPS)

11.67

43.51

42.76

36.45

43.4

57.35

failures(整体失败率)

0

0

0

11.94

21.95

41.15

响应时间(最大)

1892

2224

63084

92619

92785

91528

响应时间(最小)

36

78

153

872

1004

1

响应时间(中位数)

86

1100

2300

2900

2900

3700

响应时间(平均值)

76.74

1139.09

2344.31

8678.17

13413.85

20421.58

响应时间 latency 95%

90

1300

2500

60000

60000

60000

响应时间 latency 99%

92

1300

2600

61000

61000

61000

CPU使用率

14.16

53.05

53.08

53.04

42.71

42.73

内存使用率

29.98

30.34

30.49

30.83

31.32

32.01

AI加速卡显存平均使用率

96.44

96.44

96.44

96.44

96.44

96.44

AI加速卡算力平均使用率

32.58

120.36

120.47

136.48

119.38

134.65

分析说明

  1. 最大并发为100

  2. 30min发压时间的平均QPS 最大是42.76左右

  3. 并发超过100时,开始出现报错。

  4. 并发超过100时,加速卡算力平均使用率存在一直为96.44的情况。.

  5. 并发超过50时,AI加速卡算力平均使用率超过100%。

3.6 Pytorch-v1.10模型预测

性能指标

pod性能数据

1个并发

最大并发

中间数据

中间数据

中间数据

中间数据

单副本资源数

4/1/8G

4/1/8G

4/1/8G

4/1/8G

4/1/8G

4/1/8G

Users(并发数)

1

50

100

300

500

1000

递增速率(VU/s)

1

5

10

20

35

66

发压时间

30min

30min

30min

30min

30min

30min

发送请求数

19985

50643

49420

47723

55325

83476

req/s(TPS)

11.11

28.15

27.52

26.57

30.8

46.48

failures(整体失败率)

0

0

0.16

15.29

30.06

51.07

响应时间(最大)

123

3926

54769

92485

92408

91646

响应时间(最小)

34

165

599

228

1006

2

响应时间(中位数)

83

1800

3600

3700

6200

7300

响应时间(平均值)

81.1

1766.19

3656.31

12284.4

18043.53

24809.95

响应时间 latency 95%

87

1800

3600

60000

60000

60000

响应时间 latency 99%

89

1800

3700

67000

66000

61000

CPU使用率

11.92

26.84

26.73

23.50

24.78

22.76

AI加速卡显存平均使用率

8.87

8.87

8.87

8.87

8.87

8.87

AI加速卡算力平均使用率

6.4

出现为0情况

11

出现为0情况

30

出现为0情况

70

60

64.9

内存使用率

32.72

35.72

32.80

33.15

33.56

34.38

分析说明

  1. 最大并发为50

  2. 30min发压时间的平均TPS 最大是28.15左右

  3. 并发超过50时,开始出现报错

  4. 加速卡算力平均使用率存在一直为8.87的情况

  5. 并发小于300时,AI加速卡算力平均使用率出现为0时间段

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/9179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Matlab实现30种电力电子仿真模型(附上完整源码)

本文介绍了如何使用Matlab来实现电力电子仿真模型,并提供了一个简单的代码示例,展示了如何建立一个逆变器的仿真模型并进行仿真分析。 文章目录 1. 引言2. Matlab实现电力电子仿真模型的基本步骤3. 逆变器仿真模型的示例代码4. 结果分析5. 结论6. 30个完…

如何备份与恢复MySQL数据库数据

目录 数据备份的重要性 造成数据丢失的原因 备份的主要目的 日志 数据库备份类型 逻辑备份 完全备份 差异备份 增份(增量备份) 备份方式比较 三、常见的备份方法 物理冷备 专用备份工具mysqldump 或mysqlhotcopy 启用二进制日志进行增量备份…

第5讲-搭建kubernetes集群

一、minikube ​ minikube 是一个工具, 能让你在本地运行 Kubernetes。 minikube 在你的个人计算机(包括 Windows、macOS 和 Linux PC)上运行一个一体化(all-in-one)或多节点的本地 Kubernetes 集群,以便你…

所有docker命令无效,解决办法

目录 ■前言 今天使用docker时,所有命令无效 ■解决办法如下 1.停止docker服务 2.查看状态 3.删除之前的docker相关的文件 4.再次查看状态 5.使用相关命令 (好用了) 6.重新下载镜像 ■前言 今天使用docker时,所有命令无…

DES加密的基本常识和封装类

DES加密的基本常识和封装类 DES(Data Encryption Standard)是一种对称加密算法,它是在1977年由IBM所提出,并在1981年被美国国家标准局(NIST)确定为数据加密标准。DES使用相同的密钥对数据进行加密和解密&a…

Python + Playwright 无头浏览器Chrome找不到元素

用Python Playwright调试时,发现不用无头浏览器(即headlessFalse)代码能够运行成功,但是一用无头浏览器时(即headlessTrue)就会报错,提示找不到元素。换成Firefox浏览器又不会有这个问题&#…

redhat官网下载7.9版本iso

redhat官方地址 https://developers.redhat.com/products/rhel/download 下载前会让你先登录,如果没有账号就需要先去注册账号哟。

《向量数据库指南》:向量数据库Pinecone备份索引教程

目录 ⚠️警告 使用集合创建备份 检查集合的状态 列出您的集合 删除一个集合 本文档描述如何使用集合备份索引。 要了解如何从集合创建索引,请参阅管理索引。 ⚠️警告 本文档使用集合。这是一个公开预览功能。在使用此功能生产负载之前,请进行充分测试。 使用集合…

利用OpenMP优化Opencv图像处理

当使用OpenMP进行图像处理时&#xff0c;可以通过线程ID来控制每个线程处理的行数位置&#xff0c;实现并行处理图像的不同部分。以下是一个示例代码&#xff0c;展示了如何使用OpenMP对图像进行并行处理&#xff1a; #include <iostream> #include <opencv2/opencv.…

webpack xxx is not a constructor

环境 webpack5.88.2 vue-router 按需引入 原因 模块循环引用导致 有A B C三个模块 A B模块import C 中导出的class c又依赖B 中Class 的方法 B 又依赖C中的class 此时会导致import 的 C 为undefined

【C语言】9-三大结构之选择结构-3

1. 综合举例 1.1 例1 编写一个程序完成输入一个 1-7 中的数字,输出对应的是星期几 这里推荐使用 Visio 或者类似的软件来画一个流程图。在进行程序设计时,尤其是大型项目时,软件流程图可以帮助我们很好的分析程序的结构以及结构需求,跟着流程图来写程序可以让写出来的程序…

【Matlab】基于长短期记忆网络的数据分类预测(Excel可直接替换数据)

【Matlab】基于长短期记忆网络的数据分类预测(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码6.完整代码7.运行结果1.模型原理 “基于长短期记忆网络的数据分类预测”是一种利用长短期记忆网络(Long Short-Term Memory, LSTM)进行数据分类任务…

【C++】多态原理剖析,Visual Studio开发人员工具使用查看类结构cl /d1 reportSingleClassLayout

author&#xff1a;&Carlton tag&#xff1a;C topic&#xff1a;【C】多态原理剖析&#xff0c;Visual Studio开发人员工具使用查看类结构cl /d1 reportSingleClassLayout website:黑马程序员C tool&#xff1a;Visual Studio 2019 date&#xff1a;2023年7月24日 目…

【每日一个知识点二】原型链

我都是想到啥写啥&#xff0c;丝毫没有规律。前面聊到箭头函数没有原型&#xff0c;就想到了再整理一篇原型链的。 原型 原型是JavaScript中对象的一个属性&#xff0c;它指向另一个对象&#xff0c;用于实现继承关系。每个对象都有一个原型属性__proto__&#xff0c;它指向它…

hypery 十一、命令行

教程&#xff1a;Hyperf symfony/console composer地址&#xff1a; symfony/console - Packagist github地址&#xff1a;GitHub - symfony/console: Eases the creation of beautiful and testable command line interfaces hyperf/command github地址:https://github.com/…

Ubuntu18.04未安装Qt报qt.qpa.plugin could not load the Qt platform plugin xcb问题的解决方法

在Ubuntu 18.04开发机上安装了Qt 5.14.2&#xff0c;当将其可执行程序拷贝到另一台未安装Qt的Ubuntu 18.04上报错&#xff1a;拷贝可执行程序前&#xff0c;使用ldd将此执行程序依赖的动态库也一起拷贝过去&#xff0c;包括Qt5.14.2/5.14.2/gcc_64/plugins目录系的platforms目录…

【UE5 多人联机教程】05-生成玩家

步骤 1. 新建一个游戏模式基础 命名为“GM_Lobby” 2. 新建一个玩家控制器&#xff0c;命名为“PC_Lobby” 3. 新建一个游戏状态基础 命名为“GS_Lobby” 重新设置游戏模式重载、玩家控制器类、游戏状态类 4. 新建一个控件蓝图&#xff0c;命名为“UMG_Lobby” 打开“UMG_Lobb…

达闼面试(部分)(未完全解析)

grpc怎么解决负载均衡问题? Answer by newBing : gRPC提供了多种负载均衡策略&#xff0c;包括轮询、随机、最少连接数等。gRPC客户端可以使用这些策略来选择要连接的服务器。 k8s环境下部署grpc的几种方案 : 在k8s环境中&#xff0c;可以选择headless service&#xff0c;或者…

通过wait和notify来协调线程执行顺序

为什么要协调线程执行顺序 wait和notify是多线程编程中的重要工具&#xff0c;多线程调度是随机的&#xff0c;很多时候希望多个线程能够按照我们规定的顺序来执行&#xff0c;完成线程之间的配合工作 注意事项 1.要想让notify能够顺利唤醒wait&#xff0c;就需要确保wait和no…

PostgreSQL-视图-03-查询对象依赖关系视图-dba_dependencies

PostgreSQL查询对象依赖关系视图 -- PostgreSQL查询对象依赖关系视图drop view if exists tzq.dba_dependencies; create view tzq.dba_dependencies as with source_obj as (select sp.oid,sp.proname,unnest(string_to_array(regexp_replace(regexp_replace(lower(sp.prosrc…