pub struct Gpu { /* private fields */ }Expand description
一块 N 卡上的上下文、载好的内核模块和函数表。所有方法取 &self,可以跨线程共享。
Implementations§
Source§impl Gpu
impl Gpu
Sourcepub fn alloc(&self, len: usize) -> Result<DeviceBuffer<'_>, String>
pub fn alloc(&self, len: usize) -> Result<DeviceBuffer<'_>, String>
分配 len 个 f32 的显存(内容未初始化)。len 为 0 时不调驱动。
Examples found in repository?
examples/gpu_bench.rs (line 83)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Sourcepub fn upload(&self, data: &[f32]) -> Result<DeviceBuffer<'_>, String>
pub fn upload(&self, data: &[f32]) -> Result<DeviceBuffer<'_>, String>
分配显存并拷入 data。
Examples found in repository?
examples/gpu_bench.rs (line 82)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Source§impl Gpu
impl Gpu
Sourcepub fn gemm_device(
&self,
a: &DeviceBuffer<'_>,
b: &DeviceBuffer<'_>,
c: &mut DeviceBuffer<'_>,
m: usize,
n: usize,
k: usize,
) -> Result<(), String>
pub fn gemm_device( &self, a: &DeviceBuffer<'_>, b: &DeviceBuffer<'_>, c: &mut DeviceBuffer<'_>, m: usize, n: usize, k: usize, ) -> Result<(), String>
c[m×n] = a[m×k] · b[k×n],三者都在显存、行优先。
Examples found in repository?
examples/gpu_bench.rs (line 85)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Sourcepub fn conv2d_device(
&self,
x: &DeviceBuffer<'_>,
w: &DeviceBuffer<'_>,
bias: Option<&DeviceBuffer<'_>>,
s: &ConvShape,
) -> Result<DeviceBuffer<'_>, String>
pub fn conv2d_device( &self, x: &DeviceBuffer<'_>, w: &DeviceBuffer<'_>, bias: Option<&DeviceBuffer<'_>>, s: &ConvShape, ) -> Result<DeviceBuffer<'_>, String>
二维卷积,输入、权重、偏置、输出都在显存。返回 [o, OH, OW] 的新显存。
Sourcepub fn conv2d_device_into(
&self,
x: &DeviceBuffer<'_>,
w: &DeviceBuffer<'_>,
bias: Option<&DeviceBuffer<'_>>,
s: &ConvShape,
out: &mut DeviceBuffer<'_>,
) -> Result<(), String>
pub fn conv2d_device_into( &self, x: &DeviceBuffer<'_>, w: &DeviceBuffer<'_>, bias: Option<&DeviceBuffer<'_>>, s: &ConvShape, out: &mut DeviceBuffer<'_>, ) -> Result<(), String>
同 Gpu::conv2d_device,结果写进调用方给的显存 out(长度 o·OH·OW),省一次分配;
连续推理时可以复用输出缓冲。im2col 的临时显存仍在每次调用里分配。
Examples found in repository?
examples/gpu_bench.rs (line 186)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Sourcepub fn activate_device(
&self,
x: &mut DeviceBuffer<'_>,
act: Activation,
) -> Result<(), String>
pub fn activate_device( &self, x: &mut DeviceBuffer<'_>, act: Activation, ) -> Result<(), String>
原地激活,语义同 Activation::apply。
Sourcepub fn add_bias_device(
&self,
x: &mut DeviceBuffer<'_>,
bias: &DeviceBuffer<'_>,
hw: usize,
) -> Result<(), String>
pub fn add_bias_device( &self, x: &mut DeviceBuffer<'_>, bias: &DeviceBuffer<'_>, hw: usize, ) -> Result<(), String>
原地加偏置:x 是 [C, hw],x[c, i] += bias[c]。
Sourcepub fn matmul(&self, a: &Tensor, b: &Tensor) -> Result<Vec<f32>, String>
pub fn matmul(&self, a: &Tensor, b: &Tensor) -> Result<Vec<f32>, String>
矩阵乘(同 pagesift_infer::ops::matmul):a 是 [M, K],b 是 [K, N],返回 [M, N] 行优先。
Examples found in repository?
examples/gpu_bench.rs (line 87)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Sourcepub fn conv2d(
&self,
x: &Tensor,
w: &Tensor,
bias: Option<&[f32]>,
stride: (usize, usize),
pad: (usize, usize),
dilation: (usize, usize),
groups: usize,
) -> Result<Vec<f32>, String>
pub fn conv2d( &self, x: &Tensor, w: &Tensor, bias: Option<&[f32]>, stride: (usize, usize), pad: (usize, usize), dilation: (usize, usize), groups: usize, ) -> Result<Vec<f32>, String>
二维卷积(同 pagesift_infer::ops::conv2d):x 是 [C, H, W],w 是 [O, C/groups, kh, kw];
返回 [O, OH, OW] 行优先的数据。
Examples found in repository?
examples/gpu_bench.rs (line 191)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Source§impl Gpu
impl Gpu
Sourcepub fn open() -> Result<Gpu, String>
pub fn open() -> Result<Gpu, String>
打开 0 号 N 卡,同 Gpu::open_index(0)。
Examples found in repository?
examples/gpu_bench.rs (line 63)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Sourcepub fn open_index(index: usize) -> Result<Gpu, String>
pub fn open_index(index: usize) -> Result<Gpu, String>
打开第 index 块 N 卡:载入驱动、取主上下文、按算力挑 PTX 并 JIT。
没有驱动、没有这块卡、算力低于 6.1、JIT 失败或 PAGESIFT_GPU=off 时返回错误(不 panic)。
Sourcepub fn name(&self) -> &str
pub fn name(&self) -> &str
设备名,例如 “NVIDIA GeForce GTX 1070”。
Examples found in repository?
examples/gpu_bench.rs (line 70)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Sourcepub fn compute_capability(&self) -> (i32, i32)
pub fn compute_capability(&self) -> (i32, i32)
算力 (主, 次),例如 (6, 1)。
Examples found in repository?
examples/gpu_bench.rs (line 70)
62fn main() {
63 let g = match Gpu::open() {
64 Ok(g) => g,
65 Err(e) => {
66 println!("没有可用的 GPU:{e}");
67 return;
68 }
69 };
70 println!("GPU:{}(算力 {:?})\n", g.name(), g.compute_capability());
71 println!(
72 "| 项目 | CPU ms | GPU 内核 ms | GPU 端到端 ms | 倍数(内核) | 倍数(端到端) | CPU GFLOPS | GPU GFLOPS |"
73 );
74 println!("|---|---:|---:|---:|---:|---:|---:|---:|");
75 let mut rng = Rng(0x9e37_79b9_7f4a_7c15);
76
77 for s in [512, 1024, 2048] {
78 let a = rng.tensor(vec![s, s]);
79 let b = rng.tensor(vec![s, s]);
80 let gflop = 2.0 * (s as f64).powi(3) / 1e9;
81 let cpu = wall_ms(3, || drop(ops::matmul(&a, &b)));
82 let (da, db) = (g.upload(&a.data).unwrap(), g.upload(&b.data).unwrap());
83 let mut dc = g.alloc(s * s).unwrap();
84 let kern = gpu_ms(&g, 20, || {
85 g.gemm_device(&da, &db, &mut dc, s, s, s).unwrap()
86 });
87 let e2e = wall_ms(5, || drop(g.matmul(&a, &b).unwrap()));
88 row(&format!("SGEMM {s}³"), gflop, cpu, kern, e2e);
89 }
90
91 // (说明, [C, H, W], [O, kh, kw], stride, pad, groups)
92 type Conv = (
93 &'static str,
94 [usize; 3],
95 [usize; 3],
96 (usize, usize),
97 (usize, usize),
98 usize,
99 );
100 let convs: [Conv; 6] = [
101 (
102 "3×3 s2 首层 3→32 @640²",
103 [3, 640, 640],
104 [32, 3, 3],
105 (2, 2),
106 (1, 1),
107 1,
108 ),
109 (
110 "1×1 64→128 @160²",
111 [64, 160, 160],
112 [128, 1, 1],
113 (1, 1),
114 (0, 0),
115 1,
116 ),
117 (
118 "3×3 64→64 @80²",
119 [64, 80, 80],
120 [64, 3, 3],
121 (1, 1),
122 (1, 1),
123 1,
124 ),
125 (
126 "3×3 s(2,1) 64→128 @48×320",
127 [64, 48, 320],
128 [128, 3, 3],
129 (2, 1),
130 (1, 1),
131 1,
132 ),
133 (
134 "深度 3×3 128 @160²",
135 [128, 160, 160],
136 [128, 3, 3],
137 (1, 1),
138 (1, 1),
139 128,
140 ),
141 (
142 "深度 7×7 96 @80²",
143 [96, 80, 80],
144 [96, 7, 7],
145 (1, 1),
146 (3, 3),
147 96,
148 ),
149 ];
150 for (name, [c, h, w], [o, kh, kw], stride, pad, groups) in convs {
151 let x = rng.tensor(vec![c, h, w]);
152 let wt = rng.tensor(vec![o, c / groups, kh, kw]);
153 let bias: Vec<f32> = rng.tensor(vec![o]).data;
154 let s = ConvShape {
155 c,
156 h,
157 w,
158 o,
159 kh,
160 kw,
161 stride,
162 pad,
163 dilation: (1, 1),
164 groups,
165 };
166 let (oh, ow) = s.out_hw();
167 let gflop = 2.0 * (o * oh * ow * (c / groups) * kh * kw) as f64 / 1e9;
168 let cpu = wall_ms(3, || {
169 drop(ops::conv2d(
170 &x,
171 &wt,
172 Some(&bias),
173 stride,
174 pad,
175 (1, 1),
176 groups,
177 ))
178 });
179 let (dx, dw, db) = (
180 g.upload(&x.data).unwrap(),
181 g.upload(&wt.data).unwrap(),
182 g.upload(&bias).unwrap(),
183 );
184 let mut out = g.alloc(o * oh * ow).unwrap();
185 let kern = gpu_ms(&g, 20, || {
186 g.conv2d_device_into(&dx, &dw, Some(&db), &s, &mut out)
187 .unwrap()
188 });
189 let e2e = wall_ms(5, || {
190 drop(
191 g.conv2d(&x, &wt, Some(&bias), stride, pad, (1, 1), groups)
192 .unwrap(),
193 )
194 });
195 row(name, gflop, cpu, kern, e2e);
196 }
197}Sourcepub fn memory_free(&self) -> Result<u64, String>
pub fn memory_free(&self) -> Result<u64, String>
现在的空闲显存(字节)。
Trait Implementations§
Auto Trait Implementations§
impl Forget for Gpu
impl Freeze for Gpu
impl Move for Gpu
impl RefUnwindSafe for Gpu
impl Unpin for Gpu
impl UnsafeUnpin for Gpu
impl UnwindSafe for Gpu
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more