How to convert vector<int> into c++ torch tensor?

markb: <p>Hi,<br>
I have a vector of int. All I want is to convert such vector into torch tensor.<br>
I tried this:</p>
<pre><code class="lang-auto">vector&lt;int&gt; x = {10, 15, 20, 100, 500};
vector&lt;torch::jit::IValue&gt; inputs;
inputs.push_back(torch::from_blob(x.data(), {1, x.size()}, torch::kInt64));
</code></pre>
<p>But that returns me different numbers(see below).</p>
<pre><code class="lang-auto">6.4425e+10  4.2950e+11  1.3972e+14  2.5700e+02  9.4817e+13
[ Variable[CPULongType]{1,5} ]
</code></pre>
<p>What I can still do is  this:</p>
<pre><code class="lang-auto">vector&lt;int&gt; x = {10, 15, 20, 100, 500};
vector&lt;torch::jit::IValue&gt; inputs;
torch::Tensor t = torch::zeros({1, (int)x.size()}, torch::kInt64);
int counter = 0;
for (int i : x)
{
    t[0][counter] = i;
    counter++;
}
inputs.push_back(t);
</code></pre>
<p>But is not there other way how to convert vector into torch::Tensor?</p>

dhpollack: <p>I had some issues creating tensors with a long type directly, but I’m sure that is more that I don’t know what I’m doing in c++ rather than it not working.  However, I did something like the following recently for this.</p>
<pre><code class="lang-auto">vector&lt;int&gt; v({1, 2, 3});
auto opts = torch::TensorOptions().dtype(torch::kInt32);
torch::Tensor t = torch::from_blob(t.data(), {3}, opts).to(torch::kInt64);
</code></pre>

markb: <p>Thanks for the reply. It worked <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"> I think my problem was setting its type directly to <code> torch::kInt64</code> instead of setting it to <code> torch::kInt32</code> and then converting it to  <code> torch::kInt64</code>.</p>

dhpollack: <p>No worries, mini-update to the answer.  If one makes <code>vector&lt;int&gt;</code> a <code>vector&lt;long&gt;</code> then you can directly convert to a long tensor.</p>

HarveySpecter: <p>I ran into a similar issue and figured the problem is due to <code>torch::from_blob</code> not taking ownership of the vector from which the tensor has been created. Solution for this is to use <code>torch::from_blob</code> with <code>clone()</code>.</p>
<p>For example, in the OP’s question, if the <code>inputs</code> are created from a vector <code>vec</code> in a certain scope, but used when <code>vec</code> is no longer in scope, then the <code>inputs</code> is likely to have garbage values.</p>
<pre><code class="lang-auto">    torch::Tensor inputs, cloned_inputs;
    {
        std::vector&lt;long&gt; vec = {10, 15, 20, 100, 500};
        auto options = torch::TensorOptions().dtype(at::kLong);
        inputs = torch::from_blob(vec.data(), {1, vec.size()}, options);
        cloned_inputs = torch::from_blob(vec.data(), {1, vec.size()}, options).clone();
        std::cout &lt;&lt; "inputs within scope of vec: \n" &lt;&lt; inputs &lt;&lt; std::endl;
        std::cout &lt;&lt; "cloned_inputs within scope of vec: \n" &lt;&lt; cloned_inputs &lt;&lt; std::endl;
    }
    std::cout &lt;&lt; "inputs beyond scope of vec: \n" &lt;&lt; inputs &lt;&lt; std::endl;
    std::cout &lt;&lt; "cloned_inputs beyond scope of vec: \n" &lt;&lt; cloned_inputs &lt;&lt; std::endl;
</code></pre>
<p>This ouputs:</p>
<pre><code class="lang-auto">inputs within scope of vec: 
  10   15   20  100  500
[ CPULongType{1,5} ]
cloned_inputs within scope of vec: 
  10   15   20  100  500
[ CPULongType{1,5} ]
inputs beyond scope of vec: 
 9.4045e+13  1.0000e+00  1.0000e+00  0.0000e+00  5.0000e+02
[ CPULongType{1,5} ]
cloned_inputs beyond scope of vec: 
  10   15   20  100  500
[ CPULongType{1,5} ]
</code></pre>

phetdam: <p>So there is a way to do this <em>without</em> copying the vector’s data by use of <a href="https://en.cppreference.com/w/cpp/utility/move" rel="noopener nofollow ugc">move semantics</a> and <a href="https://en.cppreference.com/w/cpp/language/new#Placement_new" rel="noopener nofollow ugc">placement new</a>. The overall idea here is that we can <code>std::move</code> from the vector or another object that stores data in a contiguous buffer, placement <code>new</code> into a managed buffer, and then use <code>torch::from_blob</code> with a custom deleter that will clean up the memory on tensor deletion.</p>
<p>For simplicity I show the C++17 approach; I’ve used this before with success.</p>
<pre data-code-wrap="cpp"><code class="lang-cpp">// traits classes for PyTorch tensor type constants
template &lt;typename T&gt;
struct tensor_type_traits {};

// for 32-bit signed int
template &lt;&gt;
struct tensor_type_traits&lt;int&gt; {
  static constexpr auto typenum = torch::kInt32;
};

// ... e.g. for double (kFloat64), float (kFloat32), etc.

/**
 * Return a 1D PyTorch tensor from an STL vector.
 *
 * @tparam T Element type
 * @tparam A Allocator type
 *
 * @param vec Vector to consume
 * @param options Tensor creation options
 */
template &lt;typename T, typename A&gt;
torch::Tensor make_tensor(
  std::vector&lt;T, A&gt;&amp;&amp; vec, torch::TensorOptions options = {})
{
  using V = std::vector&lt;T, A&gt;;
  // allocate storage for placement new (on exception also prevents leaks)
  auto buf = std::make_unique&lt;unsigned char[]&gt;(sizeof(V));
  // placement new + get pointer to moved vector
  auto vptr = new(buf.get()) V{std::move(vec)};
  // create PyTorch 1D tensor
  auto ten = torch::from_blob(
    vptr-&gt;data(),
    {vptr-&gt;size()},
    // note: argument is unused since we are deleting through vptr
    [vptr](void*)
    {
      // take ownership of the buffer for later deletion on scope exit
      std::unique_ptr&lt;unsigned char[]&gt; vbuf{(unsigned char*) vptr};
      vptr-&gt;~V();
    },
    // data type determined via traits class specializations
    options.dtype(tensor_type_traits&lt;T&gt;::typenum)
  );
  // we only release the buffer now in case from_blob throws
  buf.release();
  return ten;
}
</code></pre>
<p>We can use the <code>make_tensor()</code> function template as follows:</p>
<pre data-code-wrap="cpp"><code class="lang-cpp">// some STL vector
std::pmr::vector&lt;double&gt; vec{4., 2.322, 2.432, 6.34, 5.343};
// create 1D tensor with gradient requirement by consuming vector
auto ten = make_tensor(std::move(vec), torch::requires_grad());
// ...
</code></pre>
<p>You do need to be careful that you are not resizing <code>ten</code> because the <code>Tensor</code> does not actually know anything about its underlying storage but if you just need a tensor as an input so you can call <code>backward()</code> and <code>grad()</code> this is sufficient. Of course, this can be extended if necessary.</p>
<p>I’ve made similar overloads for Eigen3 matrices; since they can be row- or column-major (defaulting to the latter), a bit of <code>if constexpr</code> is required to determine strides.</p>