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) {
552 if (order[k] < 0 || order[k] >= rank)
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);
#define EVE_TENSOR_UNARY(name, opType)
float32 / int32 tensor (rank 1–6), row-major. Eager: owns a buffer. Symbolic: node in a Func graph (n...
Tensor * mulScalar(float s) const
Tensor * reshape5(int d0, int d1, int d2, int d3, int d4) const
Tensor * sub(const Tensor *other) const
float reduceSum() const
归约:求和 / 均值 / 最小 / 最大。
void ensureEager(const char *op) const
Tensor * add(const Tensor *other) const
Eager 逐元素运算(符号张量会抛异常)。
void copyFrom(const Tensor *other)
void set3(int i0, int i1, int i2, float value)
void addScalarInPlace(float s)
static constexpr int kMaxRank
Tensor * reshape4(int d0, int d1, int d2, int d3) const
float get3(int i0, int i1, int i2) const
float get4(int i0, int i1, int i2, int i3) const
std::vector< float > dequantized() const
void mulScalarInPlace(float s)
float get5(int i0, int i1, int i2, int i3, int i4) const
Tensor * reshape6(int d0, int d1, int d2, int d3, int d4, int d5) const
Tensor * reshape2(int d0, int d1) const
float * data()
原始数据指针(eager)。
Tensor * clamp(float lo, float hi) const
Tensor * reshape1(int d0) const
float dot(const Tensor *other) const
float get6(int i0, int i1, int i2, int i3, int i4, int i5) const
Tensor * divScalar(float s) const
Tensor * multiply(const Tensor *other) const
float get2(int i0, int i1) const
Tensor * powScalar(float exp) const
Tensor * subScalar(float s) const
void set1(int i0, float value)
int getDim(int axis) const
Tensor * transpose() const
void set(int flatIndex, float value)
void set4(int i0, int i1, int i2, int i3, float value)
float get(int flatIndex) const
Tensor * maximumScalar(float s) const
Tensor * div(const Tensor *other) const
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)
Tensor * reshape3(int d0, int d1, int d2) const
void multiplyInPlace(const Tensor *other)
Tensor * matmul(const Tensor *other) const
矩阵乘法 / 转置 / 变形。
Tensor * minimumScalar(float s) const
Tensor * addScalar(float s) const
Tensor * permute(const int *order, int rank) const
static int product(const int *dims, int rank)
void addInPlace(const Tensor *other)
Eager 原地运算。
void set6(int i0, int i1, int i2, int i3, int i4, int i5, float value)
void set5(int i0, int i1, int i2, int i3, int i4, float value)
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)
void permute(const float *in, const int *inDims, int rank, const int *order, float *out, const int *outDims)
bool broadcastShape(const int *aDims, int aRank, const int *bDims, int bRank, int *outDims, int &outRank)
void unaryOp(OpType type, const float *in, int count, float *out, float s0, float s1)
void dequantizeAll(DType dt, const uint8_t *bytes, const float *scales, int group, int count, float *out)
float dequantValue(DType dt, const uint8_t *bytes, const float *scales, int group, int idx)
bool isQuantDType(DType dt)
bool parseDType(const std::string &name, DType &out)
DType
Tensor element types.
const char * dtypeName(DType dtype)