tensorflow/core/framework/tensor_test.cc
// On the alignment.
//
// As of 2018/5, tensorflow::Tensor allocates its buffer with 64-byte
// alignment. Tensor::tensor/flat/vec/matrix methods requires the
// buffer satisfies Eigen::Aligned (e.g., 16-bytes aligned usually,
// 32-bytes for AVX, and 64-bytes for AVX512). Tensor::Slice requires
// the caller to ensure its result is aligned if the caller intends
// to use those methods. In this test case, we simply make sure each
// slice is 64-byte aligned: sizeof(float) * 4 * 36 = 576.  576 % 64 = 0.
On the alignment.
As of 2018/5, tensorflow::Tensor allocates its buffer with 64-byte
alignment. Tensor::tensor/flat/vec/matrix methods requires the
buffer satisfies Eigen::Aligned . Tensor::Slice requires
the caller to ensure its result is aligned if the caller intends
to use those methods. In this test case, we simply make sure each
slice is 64-byte aligned: sizeof(float) * 4 * 36 = 576.
On the alignment . As of 2018 / 5 tensorflow :: Tensor allocates its buffer with 64 - byte alignment . Tensor :: tensor / flat / vec / matrix methods requires the buffer satisfies Eigen :: Aligned . Tensor :: Slice requires the caller to ensure its result is aligned if the caller intends to use those methods . In this test case we simply make sure each slice is 64 - byte aligned : sizeof ( float ) * 4 * 36 = 576 .
TEST(Tensor, Slice_Basic) {
  Tensor saved;
  {  
    Tensor x(DT_FLOAT, TensorShape({10, 4, 36}));
    for (int i = 0; i < 10; ++i) {
      x.Slice(i, i + 1).flat<float>().setConstant(i * 1.f);
    }
    Tensor y = x.Slice(4, 8);
    EXPECT_TRUE(y.shape().IsSameSize(TensorShape({4, 4, 36})));
    auto tx = x.tensor<float, 3>();
    auto ty = y.tensor<float, 3>();
    for (int i = 0; i < 4; ++i) {
      for (int j = 0; j < 4; ++j) {
        for (int k = 0; k < 36; ++k) {
          EXPECT_EQ(ty(i, j, k), 4.0 + i);
          EXPECT_EQ(&tx(4 + i, j, k), &ty(i, j, k));
        }
      }
    }
    TestCopies<float>(y);
    y = x.Slice(0, 10);
    ExpectEqual<float>(x, y);
    EXPECT_EQ(x.flat<float>().data(), y.flat<float>().data());
    auto z = x.Slice(4, 8).Slice(2, 3);
    auto tz = z.tensor<float, 3>();
    EXPECT_EQ(1, z.dim_size(0));
    for (int j = 0; j < 4; ++j) {
      for (int k = 0; k < 36; ++k) {
        EXPECT_EQ(tz(0, j, k), 6.0);
      }
    }
    saved = z;
  }
  {
    EXPECT_EQ(1, saved.dim_size(0));
    auto tsaved = saved.tensor<float, 3>();
    for (int j = 0; j < 4; ++j) {
      for (int k = 0; k < 36; ++k) {
        EXPECT_EQ(tsaved(0, j, k), 6.0);
      }
    }
  }
  {  
    Tensor x(DT_FLOAT, TensorShape({10, 0, 36}));
    x.flat<float>().setRandom();
    Tensor y = x.Slice(4, 8);
    EXPECT_TRUE(y.shape().IsSameSize(TensorShape({4, 0, 36})));
  }
  {
    Tensor x(DT_FLOAT, TensorShape({30}));
    x.flat<float>().setConstant(0.0);
    Tensor y = x.Slice(1, 13);
#if EIGEN_MAX_ALIGN_BYTES > 0
    EXPECT_FALSE(y.IsAligned());
#endif
    y.unaligned_flat<float>().setConstant(1.0);
    for (int64_t i = 0; i < y.NumElements(); ++i) {
      EXPECT_EQ(1.0, y.unaligned_flat<float>()(i));
    }
  }
}
TEST ( Tensor , Slice_Basic ) { Tensor saved ; { Tensor x ( DT_FLOAT , TensorShape ( { 10 , 4 , 36 } ) ) ; for ( int i = 0 ; i < 10 ; ++ i ) { x . Slice ( i , i + 1 ) . flat < float > ( ) . setConstant ( i * 1.f ) ; } Tensor y = x . Slice ( 4 , 8 ) ; EXPECT_TRUE ( y . shape ( ) . IsSameSize ( TensorShape ( { 4 , 4 , 36 } ) ) ) ; auto tx = x . tensor < float , 3 > ( ) ; auto ty = y . tensor < float , 3 > ( ) ; for ( int i = 0 ; i < 4 ; ++ i ) { for ( int j = 0 ; j < 4 ; ++ j ) { for ( int k = 0 ; k < 36 ; ++ k ) { EXPECT_EQ ( ty ( i , j , k ) , 4.0 + i ) ; EXPECT_EQ ( & tx ( 4 + i , j , k ) , & ty ( i , j , k ) ) ; } } } TestCopies < float > ( y ) ; y = x . Slice ( 0 , 10 ) ; ExpectEqual < float > ( x , y ) ; EXPECT_EQ ( x . flat < float > ( ) . data ( ) , y . flat < float > ( ) . data ( ) ) ; auto z = x . Slice ( 4 , 8 ) . Slice ( 2 , 3 ) ; auto tz = z . tensor < float , 3 > ( ) ; EXPECT_EQ ( 1 , z . dim_size ( 0 ) ) ; for ( int j = 0 ; j < 4 ; ++ j ) { for ( int k = 0 ; k < 36 ; ++ k ) { EXPECT_EQ ( tz ( 0 , j , k ) , 6.0 ) ; } } saved = z ; } { EXPECT_EQ ( 1 , saved . dim_size ( 0 ) ) ; auto tsaved = saved . tensor < float , 3 > ( ) ; for ( int j = 0 ; j < 4 ; ++ j ) { for ( int k = 0 ; k < 36 ; ++ k ) { EXPECT_EQ ( tsaved ( 0 , j , k ) , 6.0 ) ; } } } { Tensor x ( DT_FLOAT , TensorShape ( { 10 , 0 , 36 } ) ) ; x . flat < float > ( ) . setRandom ( ) ; Tensor y = x . Slice ( 4 , 8 ) ; EXPECT_TRUE ( y . shape ( ) . IsSameSize ( TensorShape ( { 4 , 0 , 36 } ) ) ) ; } { Tensor x ( DT_FLOAT , TensorShape ( { 30 } ) ) ; x . flat < float > ( ) . setConstant ( 0.0 ) ; Tensor y = x . Slice ( 1 , 13 ) ; #if EIGEN_MAX_ALIGN_BYTES > 0 EXPECT_FALSE ( y . IsAligned ( ) ) ; #endif y . unaligned_flat < float > ( ) . setConstant ( 1.0 ) ; for ( int64_t i = 0 ; i < y . NumElements ( ) ; ++ i ) { EXPECT_EQ ( 1.0 , y . unaligned_flat < float > ( ) ( i ) ) ; } } }
On the alignment.
On the alignment .
// General // Fills in known values. // A simple slice along dim0. // A simple slice equivalent to identity. // A slice of a slice. // x and y will be out of scope. But 'saved' should be alive. // Empty // Test unaligned access via a Slice. // Take an unaligned slice.