15int productLocal(
const int *dims,
int rank) {
17 for (
int i = 0; i < rank; ++i) {
18 if (dims[i] <= 0)
throw eve::Exception(
"Tensor: dims must be > 0");
35 default:
return "float32";
40 if (
name ==
"float32" ||
name ==
"f32") {
44 if (
name ==
"int32" ||
name ==
"i32") {
48 if (
name ==
"fp16" ||
name ==
"f16") {
60 if (
name ==
"int8" ||
name ==
"i8") {
64 if (
name ==
"int4" ||
name ==
"i4") {
71int Tensor::product(
const int *dims,
int rank) {
return productLocal(dims, rank); }
73void Tensor::initDims(
DType dtype,
const int *dims,
int rank) {
77 for (
int i = 0; i <
kMaxRank; ++i) dims_[i] = 0;
78 for (
int i = 0; i < rank; ++i) dims_[i] = dims[i];
79 size_ = productLocal(dims, rank);
84 data_.assign(
static_cast<size_t>(size_), 0.f);
106 int d[] = {d0, d1, d2};
110 int d[] = {d0, d1, d2, d3};
114 int d[] = {d0, d1, d2, d3, d4};
118 int d[] = {d0, d1, d2, d3, d4, d5};
124 t->kind_ = Kind::Symbolic;
128 for (
int i = 0; i <
kMaxRank; ++i)
t->dims_[i] = 0;
129 for (
int i = 0; i < rank; ++i)
t->dims_[i] = dims[i];
130 t->size_ = productLocal(dims, rank);
137 if (kind_ != Kind::Eager)
138 throw eve::Exception(
"Tensor.%s: symbolic tensor has no value (compile/run first)", op);
142 if (axis < 0 || axis >= rank_)
throw eve::Exception(
"Tensor.getDim: axis out of range");
146int Tensor::offset2(
int i0,
int i1)
const {
148 if (i0 < 0 || i0 >= dims_[0] || i1 < 0 || i1 >= dims_[1])
150 return i0 * dims_[1] +
i1;
153int Tensor::offset3(
int i0,
int i1,
int i2)
const {
155 if (i0 < 0 || i0 >= dims_[0] || i1 < 0 || i1 >= dims_[1] || i2 < 0 || i2 >= dims_[2])
157 return (
i0 * dims_[1] +
i1) * dims_[2] +
i2;
160int Tensor::offset4(
int i0,
int i1,
int i2,
int i3)
const {
162 if (i0 < 0 || i0 >= dims_[0] || i1 < 0 || i1 >= dims_[1] || i2 < 0 || i2 >= dims_[2] ||
163 i3 < 0 || i3 >= dims_[3])
165 return ((
i0 * dims_[1] +
i1) * dims_[2] +
i2) * dims_[3] + i3;
168int Tensor::offset5(
int i0,
int i1,
int i2,
int i3,
int i4)
const {
170 if (i0 < 0 || i0 >= dims_[0] || i1 < 0 || i1 >= dims_[1] || i2 < 0 || i2 >= dims_[2] ||
171 i3 < 0 || i3 >= dims_[3] || i4 < 0 || i4 >= dims_[4])
173 return (((
i0 * dims_[1] +
i1) * dims_[2] +
i2) * dims_[3] + i3) * dims_[4] + i4;
176int Tensor::offset6(
int i0,
int i1,
int i2,
int i3,
int i4,
int i5)
const {
178 if (i0 < 0 || i0 >= dims_[0] || i1 < 0 || i1 >= dims_[1] || i2 < 0 || i2 >= dims_[2] ||
179 i3 < 0 || i3 >= dims_[3] || i4 < 0 || i4 >= dims_[4] || i5 < 0 || i5 >= dims_[5])
181 return ((((
i0 * dims_[1] +
i1) * dims_[2] +
i2) * dims_[3] + i3) * dims_[4] + i4) * dims_[5] +
198 if (flatIndex < 0 || flatIndex >= size_)
throw eve::Exception(
"Tensor.get: index out of range");
200 return data_[
static_cast<size_t>(flatIndex)];
205 if (flatIndex < 0 || flatIndex >= size_)
throw eve::Exception(
"Tensor.set: index out of range");
207 data_[
static_cast<size_t>(flatIndex)] =
value;
213 std::vector<float> out(
static_cast<size_t>(size_));
214 q::dequantizeAll(dtype_, bytes_.data(), qScales_.data(), qGroup_, size_, out.data());
219 if (rank_ != 1)
throw eve::Exception(
"Tensor.get1: expected rank 1");
223 if (rank_ != 1)
throw eve::Exception(
"Tensor.set1: expected rank 1");
228 return data_[
static_cast<size_t>(offset2(
i0,
i1))];
232 data_[
static_cast<size_t>(offset2(
i0,
i1))] =
value;
236 return data_[
static_cast<size_t>(offset3(
i0,
i1,
i2))];
240 data_[
static_cast<size_t>(offset3(
i0,
i1,
i2))] =
value;
244 return data_[
static_cast<size_t>(offset4(
i0,
i1,
i2, i3))];
248 data_[
static_cast<size_t>(offset4(
i0,
i1,
i2, i3))] =
value;
252 return data_[
static_cast<size_t>(offset5(
i0,
i1,
i2, i3, i4))];
256 data_[
static_cast<size_t>(offset5(
i0,
i1,
i2, i3, i4))] =
value;
260 return data_[
static_cast<size_t>(offset6(
i0,
i1,
i2, i3, i4, i5))];
264 data_[
static_cast<size_t>(offset6(
i0,
i1,
i2, i3, i4, i5))] =
value;
269 std::fill(data_.begin(), data_.end(),
value);
274 if (!other)
throw eve::Exception(
"Tensor.copyFrom: other is null");
276 checkSameShape(other,
"copyFrom");
277 std::memcpy(data_.data(), other->data_.data(),
sizeof(
float) *
static_cast<size_t>(size_));
278 dtype_ = other->dtype_;
283 auto *out =
new Tensor(dtype_, dims_, rank_);
285 out->device_ = device_;
289void Tensor::checkSameShape(
const Tensor *other,
const char *op)
const {
291 if (rank_ != other->rank_ || size_ != other->size_)
293 for (
int i = 0; i < rank_; ++i) {
294 if (dims_[i] != other->dims_[i])
throw eve::Exception(
"Tensor.%s: shape mismatch", op);
300Tensor *broadcastBinary(
OpType op,
const Tensor *
a,
const Tensor *
b,
const char *
name) {
301 a->ensureEager(
name);
302 b->ensureEager(
name);
305 for (
int k = 0; k <
a->getRank(); ++k) aDims[k] =
a->getDim(k);
306 for (
int k = 0; k <
b->getRank(); ++k) bDims[k] =
b->getDim(k);
311 auto *out =
new Tensor(od, orank);
313 out->data(), od, orank);
328 auto *out =
new Tensor(dtype_, dims_, rank_);
334 auto *out =
new Tensor(dtype_, dims_, rank_);
340 auto *out =
new Tensor(dtype_, dims_, rank_);
346 auto *out =
new Tensor(dtype_, dims_, rank_);
352 auto *out =
new Tensor(dtype_, dims_, rank_);
358 auto *out =
new Tensor(dtype_, dims_, rank_);
364 auto *out =
new Tensor(dtype_, dims_, rank_);
369#define EVE_TENSOR_UNARY(name, opType) \
370 Tensor *Tensor::name() const { \
371 ensureEager(#name); \
372 auto *out = new Tensor(dtype_, dims_, rank_); \
373 kernels::unaryOp((opType), data_.data(), size_, out->data_.data(), 0.f, 0.f); \
390#undef EVE_TENSOR_UNARY
394 if (lo > hi) std::swap(lo, hi);
395 auto *out =
new Tensor(dtype_, dims_, rank_);
403 checkSameShape(other,
"addInPlace");
404 float *
a = data_.data();
405 const float *
b = other->data_.data();
406 for (
int i = 0; i < size_; ++i)
a[i] +=
b[i];
412 checkSameShape(other,
"multiplyInPlace");
413 float *
a = data_.data();
414 const float *
b = other->data_.data();
415 for (
int i = 0; i < size_; ++i)
a[i] *=
b[i];
420 float *
a = data_.data();
421 for (
int i = 0; i < size_; ++i)
a[i] +=
s;
426 float *
a = data_.data();
427 for (
int i = 0; i < size_; ++i)
a[i] *=
s;
432 float *
a = data_.data();
433 for (
int i = 0; i < size_; ++i)
434 if (
a[i] < 0.f)
a[i] = 0.f;
440 for (
int i = 0; i < size_; ++i) acc += data_[static_cast<size_t>(i)];
445 return size_ > 0 ?
reduceSum() / float(size_) : 0.f;
450 if (size_ <= 0)
return 0.f;
452 for (
int i = 1; i < size_; ++i) m = std::min(m, data_[static_cast<size_t>(i)]);
458 if (size_ <= 0)
return 0.f;
460 for (
int i = 1; i < size_; ++i) m = std::max(m, data_[static_cast<size_t>(i)]);
467 checkSameShape(other,
"dot");
469 const float *
a = data_.data();
470 const float *
b = other->data_.data();
471 for (
int i = 0; i < size_; ++i) acc +=
double(
a[i]) * double(
b[i]);
479 std::vector<float> aq, bq;
480 const float *
a = data_.data();
481 const float *
b = other->data_.data();
490 if (rank_ == 2 && other->rank_ == 2) {
491 int m = dims_[0], k = dims_[1],
n = other->dims_[1];
492 if (k != other->dims_[0])
throw eve::Exception(
"Tensor.matmul: inner dims mismatch");
494 float *
c = out->data_.data();
495 for (
int i = 0; i <
m; ++i) {
496 for (
int j = 0; j <
n; ++j) {
498 for (
int t = 0;
t < k; ++
t) acc +=
double(
a[i * k +
t]) * double(
b[
t *
n + j]);
499 c[i *
n + j] = float(acc);
504 if (rank_ == 3 && other->rank_ == 3) {
505 const int batch = dims_[0];
506 const int m = dims_[1], k = dims_[2],
n = other->dims_[2];
507 if (batch != other->dims_[0] || k != other->dims_[1])
509 auto *out =
new Tensor(batch,
m,
n);
510 for (
int bb = 0; bb < batch; ++bb) {
511 const float *ap =
a + size_t(bb) *
m * k;
512 const float *bp =
b + size_t(bb) * k *
n;
513 float *
c = out->data_.data() + size_t(bb) *
m *
n;
514 for (
int i = 0; i <
m; ++i) {
515 for (
int j = 0; j <
n; ++j) {
517 for (
int t = 0;
t < k; ++
t)
518 acc +=
double(ap[i * k +
t]) * double(bp[
t *
n + j]);
519 c[i *
n + j] = float(acc);
525 throw eve::Exception(
"Tensor.matmul: expected rank 2x2 or 3x3 (got %dx%d)", rank_, other->rank_);
530 if (rank_ != 2)
throw eve::Exception(
"Tensor.transpose: expected rank 2");
535 auto *
t =
new Tensor(dims_[1], dims_[0]);
536 for (
int i = 0; i < dims_[1]; ++i)
537 for (
int j = 0; j < dims_[0]; ++j)
538 t->set2(i, j,
f[
static_cast<size_t>(j * dims_[1] + i)]);
541 int order[] = {1, 0};
547 if (rank != rank_)
throw eve::Exception(
"Tensor.permute: rank mismatch");
549 throw eve::Exception(
"Tensor.permute: quantized tensor; dequantize first");
551 for (
int k = 0; k < rank; ++k) {
554 od[k] = dims_[
order[k]];
556 auto *out =
new Tensor(dtype_, od, rank);
563 if (d0 != size_)
throw eve::Exception(
"Tensor.reshape1: size mismatch");
564 auto *out =
new Tensor(dtype_, &d0, 1);
571 if (d0 * d1 != size_)
throw eve::Exception(
"Tensor.reshape2: size mismatch");
573 auto *out =
new Tensor(dtype_,
d, 2);
580 if (d0 * d1 * d2 != size_)
throw eve::Exception(
"Tensor.reshape3: size mismatch");
581 int d[] = {d0, d1, d2};
582 auto *out =
new Tensor(dtype_,
d, 3);
589 if (d0 * d1 * d2 * d3 != size_)
throw eve::Exception(
"Tensor.reshape4: size mismatch");
590 int d[] = {d0, d1, d2, d3};
591 auto *out =
new Tensor(dtype_,
d, 4);
598 if (d0 * d1 * d2 * d3 * d4 != size_)
throw eve::Exception(
"Tensor.reshape5: size mismatch");
599 int d[] = {d0, d1, d2, d3, d4};
600 auto *out =
new Tensor(dtype_,
d, 5);
607 if (d0 * d1 * d2 * d3 * d4 * d5 != size_)
609 int d[] = {d0, d1, d2, d3, d4, d5};
610 auto *out =
new Tensor(dtype_,
d, 6);
std::map< std::string, std::vector< std::string > > graph
#define EVE_TENSOR_UNARY(name, opType)
EVENGINE_API_FOUNDATION public API.
EVENGINE_API_DOMAINS public API.
float32 / int32 tensor (rank 1–6), row-major. Eager: owns a buffer. Symbolic: node in a Func graph (n...
Tensor * mulScalar(float s) const
Mul scalar.
Tensor * reshape5(int d0, int d1, int d2, int d3, int d4) const
Reshape 5.
Tensor * sub(const Tensor *other) const
Sub.
float reduceSum() const
归约:求和 / 均值 / 最小 / 最大。
bool isQuantized() const
True when quantized.
void fill(float value)
Fill.
void ensureEager(const char *op) const
Ensure eager.
Tensor * add(const Tensor *other) const
Eager 逐元素运算(符号张量会抛异常)。
void copyFrom(const Tensor *other)
Copies from.
void set3(int i0, int i1, int i2, float value)
Sets the 3.
float reduceMax() const
Reduce max.
void addScalarInPlace(float s)
Adds scalar in place.
static constexpr int kMaxRank
Tensor * reshape4(int d0, int d1, int d2, int d3) const
Reshape 4.
float get3(int i0, int i1, int i2) const
Returns the 3.
float get1(int i0) const
Returns the 1.
float get4(int i0, int i1, int i2, int i3) const
Returns the 4.
std::vector< float > dequantized() const
Dequantized.
void mulScalarInPlace(float s)
Mul scalar in place.
float get5(int i0, int i1, int i2, int i3, int i4) const
Returns the 5.
Tensor * reshape6(int d0, int d1, int d2, int d3, int d4, int d5) const
Reshape 6.
Tensor * reshape2(int d0, int d1) const
Reshape 2.
float * data()
原始数据指针(eager)。
Tensor * clamp(float lo, float hi) const
Clamp.
Tensor * reshape1(int d0) const
Reshape 1.
float dot(const Tensor *other) const
Dot.
int nodeId() const
Node id.
float get6(int i0, int i1, int i2, int i3, int i4, int i5) const
Returns the 6.
Tensor * divScalar(float s) const
Div scalar.
Tensor * multiply(const Tensor *other) const
Multiply.
float get2(int i0, int i1) const
Returns the 2.
Graph * graph() const
Graph.
Tensor * powScalar(float exp) const
Pow scalar.
Tensor * subScalar(float s) const
Sub scalar.
void set1(int i0, float value)
Sets the 1.
int getDim(int axis) const
Returns the dim.
Tensor * transpose() const
Transpose.
void set(int flatIndex, float value)
Sets the set.
Tensor * clone() const
Deep copy. @ownership Caller deletes.
void set4(int i0, int i1, int i2, int i3, float value)
Sets the 4.
float get(int flatIndex) const
Returns the get.
Tensor * maximumScalar(float s) const
Maximum scalar.
Tensor * div(const Tensor *other) const
Div.
static Tensor * makeSymbolic(Graph *graph, int nodeId, const int *dims, int rank)
Symbolic handle into a graph node.
void set2(int i0, int i1, float value)
Sets the 2.
Tensor * reshape3(int d0, int d1, int d2) const
Reshape 3.
void multiplyInPlace(const Tensor *other)
Multiply in place.
DType dtype() const
Dtype.
void reluInPlace()
Relu in place.
Tensor * flatten() const
Flatten.
Tensor * matmul(const Tensor *other) const
矩阵乘法 / 转置 / 变形。
Tensor * minimumScalar(float s) const
Minimum scalar.
Tensor * addScalar(float s) const
Adds scalar.
float reduceMean() const
Reduce mean.
Tensor * permute(const int *order, int rank) const
Permute.
static int product(const int *dims, int rank)
Product.
void addInPlace(const Tensor *other)
Eager 原地运算。
void set6(int i0, int i1, int i2, int i3, int i4, int i5, float value)
Sets the 6.
void set5(int i0, int i1, int i2, int i3, int i4, float value)
Sets the 5.
float reduceMin() const
Reduce min.
void binaryOp(OpType type, const float *a, const int *aDims, int aRank, const float *b, const int *bDims, int bRank, float *out, const int *outDims, int outRank)
Binary op.
void permute(const float *in, const int *inDims, int rank, const int *order, float *out, const int *outDims)
Permute.
bool broadcastShape(const int *aDims, int aRank, const int *bDims, int bRank, int *outDims, int &outRank)
Broadcast shape.
void unaryOp(OpType type, const float *in, int count, float *out, float s0, float s1)
Unary op.
void dequantizeAll(DType dt, const uint8_t *bytes, const float *scales, int group, int count, float *out)
Dequantize all.
float dequantValue(DType dt, const uint8_t *bytes, const float *scales, int group, int idx)
Dequant value.
bool isQuantDType(DType dt)
True when quant d type.
bool parseDType(const std::string &name, DType &out)
Parse d type.
DType
Tensor element types.
const char * dtypeName(DType dtype)
Dtype name.