载入中...
搜索中...
未找到
OnnxNeural.cpp
浏览该文件的文档.
1#include <algorithm>
2#include <cmath>
3#include <sstream>
5
7std::optional<RuntimeTensor> executeNeural(const Node& n, const std::vector<const RuntimeTensor*>& in,
9 const auto& x = required(in, 0);
10 if (x.element != OnnxElement::Float32) return std::nullopt;
11 if (n.op == "InstanceNormalization") {
12 const auto& scale = required(in, 1);
13 const auto& bias = required(in, 2);
14 if (x.shape.size() < 3 || scale.shape != std::vector<int64_t>{x.shape[1]} || bias.shape != scale.shape ||
15 scale.element != x.element || bias.element != x.element)
16 throw Failure("InstanceNormalization shape/type mismatch");
17 const float epsilon = n.attrs.contains("epsilon") ? n.attrs.at("epsilon").real : 1e-5f;
18 if (!(epsilon > 0) || !std::isfinite(epsilon)) throw Failure("Invalid normalization epsilon");
19 size_t spatial = 1;
20 for (size_t j = 2; j < x.shape.size(); ++j) spatial *= x.shape[j];
21 if (!spatial) throw Failure("Empty InstanceNormalization");
22 if (compute) {
23 std::ostringstream s;
24 s.precision(9);
25 s << std::scientific;
26 s << "uint base=i*" << spatial << "u;precise float mean=0.0;for(uint j=0;j<" << spatial
27 << "u;++j)mean+=x0[base+j];mean/=" << spatial << ".0;precise float var=0.0;for(uint j=0;j<" << spatial
28 << "u;++j){float d=x0[base+j]-mean;var+=d*d;}float inv=inversesqrt(var/" << spatial << ".0+" << epsilon
29 << ");for(uint j=0;j<" << spatial << "u;++j)y[base+j]=(x0[base+j]-mean)*inv*x1[i%" << x.shape[1]
30 << "u]+x2[i%" << x.shape[1] << "u];";
31 return dispatchFloat(*compute, {&x, &scale, &bias}, x.shape, s.str(), count(x.shape) / spatial);
32 }
33 auto out = floats(x);
34 for (size_t i = 0; i < out.size() / spatial; ++i) {
35 float mean = 0, var = 0;
36 for (size_t j = 0; j < spatial; ++j) mean += out[i * spatial + j];
37 mean /= spatial;
38 for (size_t j = 0; j < spatial; ++j) {
39 float d = out[i * spatial + j] - mean;
40 var += d * d;
41 }
42 const float multiplier = read<float>(scale, i % x.shape[1]) / std::sqrt(var / spatial + epsilon),
43 offset = read<float>(bias, i % x.shape[1]);
44 for (size_t j = 0; j < spatial; ++j)
45 out[i * spatial + j] = (out[i * spatial + j] - mean) * multiplier + offset;
46 }
47 return make(x.element, x.shape, out);
48 }
49 if (n.op == "ConvTranspose") {
50 const auto& w = required(in, 1);
51 if (x.shape.size() != 3 || w.shape.size() != 3 || w.element != x.element || w.shape[0] != x.shape[1])
52 throw Failure("ConvTranspose requires NCL / CIO weights", DiagnosticCode::Unsupported);
53 const auto strides = attrs(n, "strides", {1}), pads = attrs(n, "pads", {0, 0}),
54 dilations = attrs(n, "dilations", {1}), extra = attrs(n, "output_padding", {0});
55 if (strides.size() != 1 || pads.size() != 2 || dilations.size() != 1 || extra.size() != 1)
56 throw Failure("ConvTranspose attribute rank mismatch");
57 const int64_t stride = strides[0], dilation = dilations[0], groups = attr(n, "group", 1), channels = x.shape[1],
58 length = x.shape[2], kernel = w.shape[2], cout = w.shape[1];
59 if (stride <= 0 || stride > 65536 || dilation <= 0 || dilation > 65536 || groups <= 0 || channels % groups ||
60 pads[0] < 0 || pads[1] < 0 || extra[0] < 0 || extra[0] >= std::max(stride, dilation) || length <= 0 ||
61 kernel <= 0 || cout <= 0)
62 throw Failure("Invalid ConvTranspose geometry");
63 if (n.attrs.contains("kernel_shape") && attrs(n, "kernel_shape", {}) != std::vector<int64_t>{kernel})
64 throw Failure("ConvTranspose kernel_shape mismatch");
65 const int64_t width = stride * (length - 1) + extra[0] + dilation * (kernel - 1) + 1 - pads[0] - pads[1],
66 outputs = cout * groups;
67 if (width <= 0 || width > INT32_MAX) throw Failure("Invalid ConvTranspose output extent");
68 std::vector<int64_t> shape{x.shape[0], outputs, width};
69 count(shape);
70 RuntimeTensor zeroBias = make(OnnxElement::Float32, {outputs}, std::vector<float>(outputs, 0));
71 const auto& bias = in.size() > 2 && in[2] ? *in[2] : zeroBias;
72 if (bias.element != x.element || bias.shape != zeroBias.shape) throw Failure("ConvTranspose bias mismatch");
73 if (compute) {
74 std::ostringstream s;
75 s << "uint pos=i%" << width << "u,o=i/" << width << "u%" << outputs << "u,batch=i/" << width * outputs
76 << "u;precise float v=x2[o];for(uint c=0;c<" << channels / groups << "u;++c)for(uint j=0;j<" << kernel
77 << "u;++j){int z=int(pos)+" << pads[0] << "-int(j)*" << dilation << ";if(z<0||z%" << stride << "!=0||z/"
78 << stride << ">=" << length << ")continue;uint ch=o/" << cout << "u*" << channels / groups
79 << "u+c;v+=x0[(batch*" << channels << "u+ch)*" << length << "u+uint(z/" << stride << ")]*x1[(ch*" << cout
80 << "u+o%" << cout << "u)*" << kernel << "u+j];}y[i]=v;";
81 return dispatchFloat(*compute, {&x, &w, &bias}, shape, s.str());
82 }
83 std::vector<float> out(count(shape));
84 for (int64_t batch = 0; batch < x.shape[0]; ++batch)
85 for (int64_t o = 0; o < outputs; ++o)
86 for (int64_t pos = 0; pos < width; ++pos) {
87 float v = read<float>(bias, o);
88 for (int64_t c = 0; c < channels / groups; ++c)
89 for (int64_t j = 0; j < kernel; ++j) {
90 int64_t z = pos + pads[0] - j * dilation;
91 if (z < 0 || z % stride || z / stride >= length) continue;
92 int64_t ch = o / cout * (channels / groups) + c;
93 v += read<float>(x, (batch * channels + ch) * length + z / stride) *
94 read<float>(w, (ch * cout + o % cout) * kernel + j);
95 }
96 out[(batch * outputs + o) * width + pos] = v;
97 }
98 return make(x.element, shape, out);
99 }
100 if (n.op == "Resize") {
101 if (in.size() > 1 && in[1] && !in[1]->bytes.empty())
102 throw Failure("Resize ROI unsupported", DiagnosticCode::Unsupported);
103 std::vector<double> scales;
104 auto shape = x.shape;
105 if (in.size() > 2 && in[2] && !in[2]->bytes.empty()) {
106 auto s = floats(*in[2]);
107 scales.assign(s.begin(), s.end());
108 if (scales.size() != shape.size()) throw Failure("Resize scales rank mismatch");
109 for (size_t j = 0; j < shape.size(); ++j) {
110 if (!(scales[j] > 0) || !std::isfinite(scales[j]) || std::floor(shape[j] * scales[j]) > INT32_MAX)
111 throw Failure("Invalid Resize scale");
112 shape[j] = static_cast<int64_t>(std::floor(shape[j] * scales[j]));
113 }
114 } else {
115 shape = ints(required(in, 3));
116 if (shape.size() != x.shape.size()) throw Failure("Resize sizes rank mismatch");
117 for (size_t j = 0; j < shape.size(); ++j) {
118 if (x.shape[j] <= 0) throw Failure("Empty Resize input");
119 scales.push_back(double(shape[j]) / x.shape[j]);
120 }
121 }
122 count(shape);
123 const auto mode = n.attrs.contains("mode") ? n.attrs.at("mode").text : "nearest",
124 coordinate = n.attrs.contains("coordinate_transformation_mode")
125 ? n.attrs.at("coordinate_transformation_mode").text
126 : "half_pixel";
127 for (auto d : x.shape)
128 if (d <= 0) throw Failure("Empty Resize input");
129 if (mode == "nearest") {
130 if (compute) {
131 std::ostringstream s;
132 s.precision(17);
133 s << "uint rest=i,source=0u;";
134 size_t stride = 1;
135 for (size_t j = shape.size(); j > 0; --j) {
136 s << "source+=uint(min(floor(float(rest%" << shape[j - 1] << "u)/" << std::scientific
137 << scales[j - 1] << ")," << double(x.shape[j - 1] - 1) << "))*" << stride
138 << "u;rest/=" << shape[j - 1] << "u;";
139 stride *= x.shape[j - 1];
140 }
141 s << "y[i]=x0[source];";
142 return dispatchFloat(*compute, {&x}, shape, s.str());
143 }
144 std::vector<float> out(count(shape));
145 for (size_t i = 0; i < out.size(); ++i) {
146 size_t rest = i, source = 0, stride = 1;
147 for (size_t j = shape.size(); j > 0; --j) {
148 source += std::min(int64_t(std::floor((rest % shape[j - 1]) / scales[j - 1])), x.shape[j - 1] - 1) *
149 stride;
150 rest /= shape[j - 1];
151 stride *= x.shape[j - 1];
152 }
153 out[i] = read<float>(x, source);
154 }
155 return make(x.element, shape, out);
156 }
157 // The speech model interpolates its final axis only. Reject other geometries explicitly.
158 for (size_t j = 0; j + 1 < shape.size(); ++j)
159 if (shape[j] != x.shape[j])
160 throw Failure("Linear Resize supports final axis only", DiagnosticCode::Unsupported);
161 if (shape.empty()) throw Failure("Resize scalar unsupported");
162 const auto width = shape.back(), old = x.shape.back();
163 if (!width) return RuntimeTensor{x.element, shape, {}};
164 auto position = [&](int64_t p) {
165 return coordinate == "half_pixel" ? (p + .5) / scales.back() - .5 : p / scales.back();
166 };
167 if (compute) {
168 std::ostringstream s;
169 s.precision(17);
170 s << std::scientific;
171 s << "uint base=i/" << width << "u*" << old
172 << "u;float p=" << (coordinate == "half_pixel" ? "(float(i%" : "float(i%") << width
173 << (coordinate == "half_pixel" ? "u)+0.5)/" : "u)/") << scales.back()
174 << (coordinate == "half_pixel" ? "-0.5" : "") << ";float t=floor(p),f=p-t;uint a=uint(clamp(t,0.0,"
175 << double(old - 1) << ")),b=uint(clamp(t+1.0,0.0," << double(old - 1)
176 << "));y[i]=x0[base+a]*(1.0-f)+x0[base+b]*f;";
177 return dispatchFloat(*compute, {&x}, shape, s.str());
178 }
179 std::vector<float> out(count(shape));
180 for (size_t i = 0; i < out.size(); ++i) {
181 double p = position(i % width), lo = std::floor(p), f = p - lo;
182 size_t base = i / width * old;
183 out[i] = static_cast<float>(read<float>(x, base + std::clamp(int64_t(lo), int64_t(0), old - 1)) * (1 - f) +
184 read<float>(x, base + std::clamp(int64_t(lo + 1), int64_t(0), old - 1)) * f);
185 }
186 return make(x.element, shape, out);
187 }
188 return std::nullopt;
189}
190} // namespace eve::tensor::onnx_detail
float w
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::map< std::string, std::vector< Key >, std::less<> > channels
eve::action::ActionSpatialBinding spatial
const std::string & s
float length
Definition CaveMesh.cpp:94
glm::vec4 p[6]
ShaderImageInput shape
glm::vec3 n
Definition Grass.cpp:63
float v
std::int32_t c
std::uint32_t width
size_t offset
std::array< float, 3 > position
std::array< float, 3 > scale
bool required
uint32_t groups
Definition OnnxGpgpu.cpp:39
std::vector< float > scales
Definition OnnxLstm.cpp:27
OnnxCompute * compute
float f
float d
float bias
std::uint32_t count
const UnitySourceAsset & source
GPU execution boundary for native ONNX; retains no model and retains compiled resources for the lifet...
Definition OnnxCompute.h:25
std::vector< int64_t > ints(const RuntimeTensor &v)
Ints.
int64_t attr(const Node &n, const char *key, int64_t fallback)
Attr.
std::vector< int64_t > attrs(const Node &n, const char *key, std::vector< int64_t > fallback)
Attrs.
std::optional< RuntimeTensor > executeNeural(const Node &, const std::vector< const RuntimeTensor * > &, OnnxCompute *)
Execute neural.
Definition OnnxNeural.cpp:7
RuntimeTensor make(OnnxElement e, std::vector< int64_t > shape, const std::vector< T > &values)
Make.
std::vector< float > floats(const RuntimeTensor &v)
Floats.
RuntimeTensor dispatchFloat(OnnxCompute &, const std::vector< const RuntimeTensor * > &, const std::vector< int64_t > &, const std::string &, size_t work=0)
Dispatches float.