Manually set Variable data in C++

username: Omegastick
cooked: <p>I’m trying to do the equivalent of <code>layer.weights.data = tensor</code> using the PyTorch C++ frontend.</p>
<p>I’ve tried a few things:</p>
<pre><code class="lang-auto">*module.named_parameters()["layer"].data&lt;float&gt;() = *vector.data();
</code></pre>
<p>This segmentation faults.</p>
<pre><code class="lang-auto">module.named_parameters()["layer"].set_data(torch::from_blob(vector.data(), tensor_size));
</code></pre>
<p>This gives <code>!is_variable() ASSERT FAILED</code>.</p>
<pre><code class="lang-auto">module.named_parameters()["layer"] = torch::from_blob(vector.data(), tensor_size);
</code></pre>
<p>This apparently doesn’t do anything. The weights afterwards don’t change.</p>
<p>Is there a way to do this in C++?</p>

username: Omegastick
cooked: <p>It’s a bit awkward, but I found you can do it with <code>memcpy</code>.</p>
<pre><code class="lang-auto">memcpy(module.named_parameters()["layer"].data&lt;float&gt;(), vector.data(), element_count);
</code></pre>

username: mhubii
cooked: <p>Hey <a class="mention" href="/u/omegastick">@Omegastick</a>,</p>
<p>how about doing this instead</p>
<pre><code class="lang-cpp">IntList sizes = net-&gt;named_parameters()["layer"].sizes();
torch::Tensor tensor = torch::from_blob(data.data(), sizes); // where data is an std::vector&lt;float&gt;

net-&gt;named_parameters()["layer"].set_data(tensor);
</code></pre>

username: Omegastick
cooked: <p>That gives:</p>
<pre><code class="lang-auto">terminate called after throwing an instance of 'c10::Error'
  what():  !is_variable() ASSERT FAILED at /home/px046/dev/pytorch/c10/core/TensorImpl.h:758, please report a bug to PyTorch. (set_sizes_and_strides at /home/px046/dev/pytorch/c10/core/TensorImpl.h:758)
</code></pre>

username: Omegastick
cooked: <p>I found an error in my original <code>memcpy</code> code. You need to multiply the number of elements by the size of the data type:</p>
<pre><code class="lang-auto">memcpy(module.named_parameters()["layer"].data&lt;float&gt;(), vector.data(), element_count * sizeof(float));
</code></pre>

username: Omegastick
cooked: <p>Hm, the <code>memcpy</code> approach I wrote above only works for small tensors. It works for 5x5 tensors but on 64x64 ones it stops working part-way through the tensor.</p>
<p>EDIT:<br>
Okay, I found the proper way to do it. You need a <code>NoGradGuard</code> and <code>Tensor::copy()</code>:</p>
<pre><code class="lang-auto">NoGradGuard guard;
module.named_parameters()["layer"].copy_(torch::from_blob(vector.data(), tensor_size));
</code></pre>

username: mhubii
cooked: <p>take care that your guard is only locally defined</p>

username: mhubii
cooked: <p>Hey <a class="mention" href="/u/omegastick">@Omegastick</a>,</p>
<p>what I dont like about your solution is that it has the <strong>potential to break other peoples code</strong>. Your solution would at least require to put it in parenthesis, e.g.</p>
<pre><code class="lang-cpp">{
    NoGradGuard guard;
    module.named_parameters()["layer"].copy_(torch::from_blob(vector.data(), tensor_size));
}
</code></pre>
<p>You could either do this or this, as mentioned above</p>
<pre><code class="lang-cpp">torch::Tensor tensor = torch::from_blob(vector.data(), tensor_size);
net-&gt;named_parameters()["layer"].set_data(tensor);
</code></pre>

username: Haihong_Qin
cooked: <p>that works for me! thanks!</p>

username: nkg114mc
cooked: <p>Hi Martin,</p>
<p>Thanks for the suggested code. I just have a quick question, can from_blob create a constant tensor by taking a constant array as input? For example, given a constant reference of a float array data_array, and try to do the following:<br>
``’<br>
torch::Tensor tensor = torch::from_blob(data_array, tensor_size);</p>
<pre><code class="lang-auto">Is there any way to make from_blob (or any other alternative method) works in this case? Thanks!</code></pre>

username: mhubii
cooked: <p>Hi <a class="mention" href="/u/nkg114mc">@nkg114mc</a>,</p>
<p>you may want to checkout the <a href="https://pytorch.org/cppdocs/notes/tensor_basics.html" rel="nofollow noopener">tensor basics</a></p>
<p>Cheers</p>
<p>Martin</p>

username: nkg114mc
cooked: <p>Thank you very much for your suggestion, mhubii!</p>

username: Eralien
cooked: <p>Maybe using const_cast?</p>