title: TensorFlow: critical graph operations assigned to cpu rather than gpu
body: <p>I have implemented a TensorFlow DNN model (2 hidden layers with elu activation functions trained on MNIST) as a Python class in order to wrap TF calls within another library with its own optimization routines and tools. </p>
  
  <p>When running some tests on a TeslaK20 I noticed that the GPU was being used at 4% of the total capacity. Therefore I looked a bit more closely to the log-device-placement and figured that all critical operations like <code>MatMul</code>, <code>Sum</code>, <code>Add</code>, <code>Mean</code> etc were being assigned to the CPU. </p>
  
  <p>The first thing that came to mind was that it was because I was using <code>dtype=float64</code>, therefore I switched to <code>dtype=float32</code>. While a lot more operations were assigned to GPU, still a good number were assigned to the CPU, like <code>Mean</code>, <code>gradient/Mean_grad/Prod</code>, <code>gradient/Mean</code>. </p>
  
  <p>So here comes my first question (I'm linking a working code example at the end), </p>
  
  <p>1) why would that be? I have written different TF models that consist of simple tensor multiplications and reductions and they run fully on GPU as long as I use single precision. </p>
  
  <p>So here comes the second question,</p>
  
  <p>2) why does TF assign the graph to different devices depending on the data type? I understand that not all kernels are implemented for GPU but I would have thought that things like <code>MatMul</code> could run on GPU for both single and double precision.</p>
  
  <p>3) Could the fact that the model is wrapped within a Python class have an effect? I do not think this is the case because as I said, it did not happen for other models wrapped similarly but that were simpler. </p>
  
  <p>4) What sort of steps can I take to run the model fully on a GPU?</p>
  
  <p>Here is a full working example of my code that I have isolated from my library </p>
  
  <p><a href="https://gist.github.com/smcantab/8ecb679150a327738102" rel="nofollow">https://gist.github.com/smcantab/8ecb679150a327738102</a> . </p>
  
  <p>If you run it and look at the output you'll see how different parts of the graph have been assigned to different devices. To see how this changes with types and devices change <code>dtype</code> and <code>device</code> within <code>main()</code> at the end of the example. Note that if I set <code>allow_soft_placement=False</code> the graph fails to initialize.</p>
  
  <p>Any word of advice would be really appreciated.</p>