Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aligned memory #220

Merged
merged 8 commits into from May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
69 changes: 4 additions & 65 deletions FAQ.md
Expand Up @@ -361,50 +361,6 @@ int main()
}
```

Or you can reuse the memory, by sharing it between `Eigen::Matrix` and `fdeep::tensor`.

```cpp
#include <iostream>
#include <eigen3/Eigen/Dense>
#include <fdeep/fdeep.hpp>

int main()
{
// use row major storage order for eigen matrix, since fdeep uses it too
using RowMajorMatrixXf = Eigen::Matrix<fdeep::float_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;

// dimensions of the eigen matrix
const int rows = 640;
const int cols = 480;

// initialize memory shared between matrix and tensor
fdeep::shared_float_vec data_vec = fplus::make_shared_ref<fdeep::float_vec>();
data_vec->resize(static_cast<std::size_t>(rows * cols));

// create eigen matrix using the memory block from the vector above
Eigen::Map<RowMajorMatrixXf, Eigen::Unaligned> mapped_matrix(
data_vec->data(),
rows, cols);

// populate mapped_matrix some way
mapped_matrix(0, 0) = 4.0f;
mapped_matrix(1, 1) = 5.0f;
mapped_matrix(4, 2) = 6.0f;

// create fdeep::tensor also using the memory block of the vector
const int tensor_channels = rows;
const int tensor_rows = 1;
const int tensor_cols = cols;
fdeep::tensor_shape tensor_shape(tensor_rows, tensor_cols, tensor_channels);
fdeep::tensor t(tensor_shape, data_vec);

// print some values to make sure the mapping is correct
std::cout << t.get(fdeep::tensor_pos(0, 0, 0)) << std::endl;
std::cout << t.get(fdeep::tensor_pos(0, 1, 1)) << std::endl;
std::cout << t.get(fdeep::tensor_pos(0, 4, 2)) << std::endl;
}
```

How to fill an `fdeep::tensor` with values, e.g., from an `std::vector<float>`?
--------------------------------------------------------------------------------

Expand All @@ -421,31 +377,14 @@ int main()
}
```

But in case one already has an `std::vector<float>` with values, one might want to re-use it.

So the `std::vector<float>` needs to be converted to `fplus::shared_ref<std::vector<float>>` for `fdeep::tensor` to accept it in its constructor.

`T` can be converted to `fplus::shared_ref<T>` by using `fplus::make_shared_ref<T>`:

```cpp
#include <fdeep/fdeep.hpp>
int main()
{
const std::vector<float> v = {1, 2, 3};
const fdeep::shared_float_vec sv(fplus::make_shared_ref<fdeep::float_vec>(v));
fdeep::tensor t(fdeep::tensor_shape(3, 1, 1), sv);
}
```

In case the original vector is no longer needed, the copy of the value can be avoided by making it an r-value with `std::move`:
In case one already has an `std::vector<float>` with values, one can just construct a `fdeep::tensor` from it, holding a copy of the values:

```cpp
#include <fdeep/fdeep.hpp>
int main()
{
const std::vector<float> v = {1, 2, 3};
const fdeep::shared_float_vec sv(fplus::make_shared_ref<fdeep::float_vec>(std::move(v)));
fdeep::tensor t(fdeep::tensor_shape(3, 1, 1), sv);
fdeep::tensor t(fdeep::tensor_shape(3, 1, 1), v);
}
```

Expand All @@ -458,8 +397,8 @@ int main()
{
const fdeep::tensor tensor(
fdeep::tensor_shape(static_cast<std::size_t>(4)),
{1, 2, 3, 4});
const std::vector<float> vec = *tensor.as_vector();
std::vector<float>{1, 2, 3, 4})});
const std::vector<float> vec = *tensor.to_vector();
}
```

Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -134,7 +134,7 @@ int main()
const auto model = fdeep::load_model("fdeep_model.json");
const auto result = model.predict(
{fdeep::tensor(fdeep::tensor_shape(static_cast<std::size_t>(4)),
{1, 2, 3, 4})});
std::vector<float>{1, 2, 3, 4})});
std::cout << fdeep::show_tensors(result) << std::endl;
}
```
Expand Down
10 changes: 8 additions & 2 deletions include/fdeep/common.hpp
Expand Up @@ -77,11 +77,17 @@ inline void assertion(bool cond, const std::string& error)
typedef Eigen::DenseIndex EigenIndex;
#endif

typedef std::vector<float_type> float_vec;
typedef std::vector<float_type> float_vec_unaligned;

template <typename T>
using aligned_vector = std::vector<T, Eigen::aligned_allocator<T>>;

typedef aligned_vector<float_type> float_vec;
typedef fplus::shared_ref<float_vec> shared_float_vec;

using ColMajorMatrixXf = Eigen::Matrix<float_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using RowMajorMatrixXf = Eigen::Matrix<float_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using MappedRowMajorMatrixXf = Eigen::Map<RowMajorMatrixXf, Eigen::Unaligned>;
using MappedRowMajorMatrixXf = Eigen::Map<RowMajorMatrixXf, Eigen::Aligned>;
using MappedColMajorMatrixXf = Eigen::Map<ColMajorMatrixXf, Eigen::Aligned>;

} } // namespace fdeep, namespace internal
2 changes: 1 addition & 1 deletion include/fdeep/convolution.hpp
Expand Up @@ -116,7 +116,7 @@ inline tensor convolve_im2col(
shared_float_vec res_vec = fplus::make_shared_ref<float_vec>();
res_vec->resize(static_cast<std::size_t>(out_depth * out_height * out_width));

Eigen::Map<ColMajorMatrixXf, Eigen::Unaligned> out_mat_map(
MappedColMajorMatrixXf out_mat_map(
res_vec->data(),
static_cast<EigenIndex>(filter_mat.mat_.rows()),
static_cast<EigenIndex>(a.cols()));
Expand Down
2 changes: 1 addition & 1 deletion include/fdeep/layers/dense_layer.hpp
Expand Up @@ -58,7 +58,7 @@ class dense_layer : public layer

const auto result_value_vectors = fplus::transform(
[this](const auto& input_part) -> float_vec
{
{
assertion(input_part.size() == n_in_,
"Invalid input value count.");
const auto bias_padded_input = bias_pad_input(input_part);
Expand Down
15 changes: 12 additions & 3 deletions include/fdeep/tensor.hpp
Expand Up @@ -41,6 +41,11 @@ class tensor
tensor(shape, fplus::make_shared_ref<float_vec>(std::move(values)))
{
}
tensor(const tensor_shape& shape, const float_vec_unaligned& values) :
tensor(shape, fplus::make_shared_ref<float_vec>(
fplus::convert_container<float_vec>(values)))
{
}
tensor(const tensor_shape& shape, float_type value) :
tensor(shape, fplus::make_shared_ref<float_vec>(shape.volume(), value))
{
Expand Down Expand Up @@ -130,6 +135,10 @@ class tensor
{
return values_;
}
float_vec_unaligned to_vector()
{
return float_vec_unaligned(fplus::convert_container<float_vec_unaligned>(*values_));
}

private:
std::size_t idx_ignore_rank(const tensor_pos& pos) const
Expand Down Expand Up @@ -183,7 +192,7 @@ inline tensor tensor_with_changed_rank(const tensor& t, std::size_t rank)
template <typename F>
tensor transform_tensor(F f, const tensor& m)
{
return tensor(m.shape(), fplus::transform(f, *m.as_vector()));
return tensor(m.shape(), fplus::transform_convert<float_vec>(f, *m.as_vector()));
}

inline tensor tensor_from_depth_slices(const std::vector<tensor>& ms)
Expand Down Expand Up @@ -807,7 +816,7 @@ inline tensor multiply_tensors(const tensors& ts_all)
if (factors_and_tensors.first.size() > 0) {
const auto factor = fplus::product(
fplus::transform(to_singleton_value, factors_and_tensors.first));
result_values = fplus::transform(
result_values = fplus::transform_convert<float_vec>(
fplus::multiply_with<float_type>(factor), result_values);
}
return tensor(ts.front().shape(), std::move(result_values));
Expand All @@ -819,7 +828,7 @@ inline tensor subtract_tensor(const tensor& a, const tensor& b)
"both tensors must have the same size");
auto result_values = fplus::zip_with(std::minus<float_type>(),
*a.as_vector(), *b.as_vector());
return tensor(a.shape(), std::move(result_values));
return tensor(a.shape(), result_values);
}

inline tensor average_tensors(const tensors& ts)
Expand Down
2 changes: 1 addition & 1 deletion test/readme_example_main.cpp
Expand Up @@ -13,6 +13,6 @@ TEST_CASE("readme_example_main, main")
const auto model = fdeep::load_model("../readme_example_model.json");
const auto result = model.predict(
{fdeep::tensor(fdeep::tensor_shape(static_cast<std::size_t>(4)),
{1, 2, 3, 4})});
fdeep::float_vec{1, 2, 3, 4})});
std::cout << fdeep::show_tensors(result) << std::endl;
}
26 changes: 13 additions & 13 deletions test/stateful_test/stateful_recurrent_tests.cpp
Expand Up @@ -3,7 +3,7 @@

using namespace fdeep;

void vec_append(std::vector<float>& results, const std::vector<float>& x){
void vec_append(fdeep::float_vec& results, const fdeep::float_vec& x){
results.insert(std::end(results), std::begin(x), std::end(x));
return;
}
Expand All @@ -14,21 +14,21 @@ int main()
outFile.open("./models/fd_results.bin", std::ios::binary);
const bool verbose = false;

const std::vector<float> x_inf_0 = {2.1, -1.2, 3.14, 1.2};
const std::vector<float> x_inf_1 = {1, 3, -2, 10};
const std::vector<float> state_0 = {40.1, -25.1};
const std::vector<float> state_1 = {34.7, 56.1};
const std::vector<float> state_2 = {-62.5, 12.0};
const std::vector<float> state_3 = {-33.0, -100.0};
const fdeep::float_vec x_inf_0 = {2.1, -1.2, 3.14, 1.2};
const fdeep::float_vec x_inf_1 = {1, 3, -2, 10};
const fdeep::float_vec state_0 = {40.1, -25.1};
const fdeep::float_vec state_1 = {34.7, 56.1};
const fdeep::float_vec state_2 = {-62.5, 12.0};
const fdeep::float_vec state_3 = {-33.0, -100.0};



// const std::vector<float> state_0 = {1.1, -2.1};
// const std::vector<float> state_1 = {2.7, 3.1};
// const std::vector<float> state_2 = {-2.5, 3.0};
// const std::vector<float> state_3 = {-2.0, -10.0};
std::vector<float> all_results = {};
std::vector<float> one_result = {};
// const fdeep::float_vec state_0 = {1.1, -2.1};
// const fdeep::float_vec state_1 = {2.7, 3.1};
// const fdeep::float_vec state_2 = {-2.5, 3.0};
// const fdeep::float_vec state_3 = {-2.0, -10.0};
fdeep::float_vec all_results = {};
fdeep::float_vec one_result = {};

// [40.1, -25.1, 34.7, 56.1, -62.5, 12.0, -33.0, -100.0]
// [1.1, -2.1, 2.7, 3.1, -2.5, 3.0, -2.0, -10.0]
Expand Down
10 changes: 5 additions & 5 deletions test/stateful_test/tf_behaivor_scripts/temp_bidi_state_in.cpp
Expand Up @@ -15,11 +15,11 @@ int main()
// bwd_initial_h = np.asarray(-2.0).reshape(1,1)
// bwd_initial_c = np.asarray(-1.2).reshape(1,1)

const std::vector<float> x_inf_0 = {1.0, 0.0, 0.0};
const std::vector<float> state_0 = {2.75};
const std::vector<float> state_1 = {1.3};
const std::vector<float> state_2 = {-2.0};
const std::vector<float> state_3 = {-1.2};
const fdeep::float_vec x_inf_0 = {1.0, 0.0, 0.0};
const fdeep::float_vec state_0 = {2.75};
const fdeep::float_vec state_1 = {1.3};
const fdeep::float_vec state_2 = {-2.0};
const fdeep::float_vec state_3 = {-1.2};

const shared_float_vec xt0(fplus::make_shared_ref<float_vec>(x_inf_0));
const shared_float_vec st0(fplus::make_shared_ref<float_vec>(state_0));
Expand Down
4 changes: 2 additions & 2 deletions test/stateful_test/tf_behaivor_scripts/temp_rnn_test.cpp
Expand Up @@ -5,8 +5,8 @@ using namespace fdeep;

int main()
{
const std::vector<float> x_inf_0 = {1.0, 0.0, 0.0};
const std::vector<float> state_0 = {10.0};
const fdeep::float_vec x_inf_0 = {1.0, 0.0, 0.0};
const fdeep::float_vec state_0 = {10.0};

const shared_float_vec xt0(fplus::make_shared_ref<float_vec>(x_inf_0));
const shared_float_vec st0(fplus::make_shared_ref<float_vec>(state_0));
Expand Down
2 changes: 1 addition & 1 deletion test_package/test_package.cpp
Expand Up @@ -5,6 +5,6 @@ int main()
{
const fdeep::tensor t(
fdeep::tensor_shape(static_cast<std::size_t>(4)),
{1, 2, 3, 4});
fdeep::float_vec{1, 2, 3, 4});
std::cout << fdeep::show_tensor(t) << std::endl;
}