Home | History | Annotate | Download | only in gpu
      1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #include "tensorflow/core/common_runtime/gpu/gpu_stream_util.h"
     17 
     18 #include "tensorflow/cc/ops/sendrecv_ops.h"
     19 #include "tensorflow/cc/ops/standard_ops.h"
     20 #include "tensorflow/core/framework/op.h"
     21 #include "tensorflow/core/framework/types.pb.h"
     22 #include "tensorflow/core/graph/graph_def_builder.h"
     23 #include "tensorflow/core/graph/node_builder.h"
     24 #include "tensorflow/core/kernels/ops_testutil.h"
     25 #include "tensorflow/core/kernels/ops_util.h"
     26 #include "tensorflow/core/lib/core/status_test_util.h"
     27 #include "tensorflow/core/platform/test.h"
     28 
     29 namespace tensorflow {
     30 namespace {
     31 
     32 class GpuStreamUtilTest : public OpsTestBase {
     33  protected:
     34 };
     35 
     36 TEST_F(GpuStreamUtilTest, BogusOpts) {
     37   auto root = Scope::NewRootScope().ExitOnError();
     38   Graph g(OpRegistry::Global());
     39   TF_ASSERT_OK(root.ToGraph(&g));
     40   std::unordered_map<int, int> node_to_stream_id;
     41   gpu_stream_util::AssignStreamsOpts opts;
     42   Status status;
     43   status = gpu_stream_util::AssignStreams(nullptr, opts, &node_to_stream_id);
     44   EXPECT_FALSE(status.ok());
     45   status = gpu_stream_util::AssignStreams(&g, opts, nullptr);
     46   EXPECT_FALSE(status.ok());
     47   opts.max_streams = 0;
     48   status = gpu_stream_util::AssignStreams(&g, opts, &node_to_stream_id);
     49   EXPECT_FALSE(status.ok());
     50   opts.max_streams = 1;
     51   opts.compute_stream = 5;
     52   status = gpu_stream_util::AssignStreams(&g, opts, &node_to_stream_id);
     53   EXPECT_FALSE(status.ok());
     54 }
     55 
     56 TEST_F(GpuStreamUtilTest, EmptyGraph) {
     57   auto root = Scope::NewRootScope().ExitOnError();
     58   Graph g(OpRegistry::Global());
     59   TF_ASSERT_OK(root.ToGraph(&g));
     60   std::unordered_map<int, int> node_to_stream_id;
     61   gpu_stream_util::AssignStreamsOpts opts;
     62   TF_ASSERT_OK(gpu_stream_util::AssignStreams(&g, opts, &node_to_stream_id));
     63   EXPECT_EQ(2, node_to_stream_id.size());  // _SOURCE and _SINK
     64 }
     65 
     66 TEST_F(GpuStreamUtilTest, SimpleGraphOneStream) {
     67   auto root = Scope::DisabledShapeInferenceScope().ExitOnError();
     68   ops::MatMul(root, {}, {});
     69   Graph g(OpRegistry::Global());
     70   TF_ASSERT_OK(root.ToGraph(&g));
     71 
     72   std::unordered_map<int, int> node_to_stream_id;
     73   gpu_stream_util::AssignStreamsOpts opts;
     74   TF_ASSERT_OK(gpu_stream_util::AssignStreams(&g, opts, &node_to_stream_id));
     75 
     76   // There should be 5 nodes assigned.
     77   EXPECT_EQ(5, node_to_stream_id.size());
     78 
     79   // All of them should have stream 0.
     80   for (const auto& it : node_to_stream_id) {
     81     EXPECT_EQ(0, it.second);
     82   }
     83 }
     84 
     85 TEST_F(GpuStreamUtilTest, SimpleGraphManyStreams) {
     86   auto root = Scope::DisabledShapeInferenceScope().ExitOnError();
     87   ops::MatMul(root, {}, {});
     88   Graph g(OpRegistry::Global());
     89   TF_ASSERT_OK(root.ToGraph(&g));
     90 
     91   std::unordered_map<int, int> node_to_stream_id;
     92   gpu_stream_util::AssignStreamsOpts opts;
     93   opts.max_streams = 3;
     94   TF_ASSERT_OK(gpu_stream_util::AssignStreams(&g, opts, &node_to_stream_id));
     95 
     96   // There should be 5 nodes assigned.
     97   EXPECT_EQ(5, node_to_stream_id.size());
     98 
     99   // All of them should have a stream in the range [0..max_streams).
    100   for (const auto& it : node_to_stream_id) {
    101     EXPECT_GE(it.second, 0);
    102     EXPECT_LT(it.second, opts.max_streams);
    103   }
    104 }
    105 
    106 TEST_F(GpuStreamUtilTest, StreamOverrides) {
    107   auto root = Scope::DisabledShapeInferenceScope().ExitOnError();
    108   ops::_Recv(root.WithOpName("input"), DT_FLOAT, "input", "/cpu:0", 0,
    109              "/device:GPU:0");
    110   Output n = ops::MatMul(root, {}, {});
    111   ops::_Send(root.WithOpName("output"), n, "output", "/device:GPU:0", 0,
    112              "/cpu:0");
    113   Graph g(OpRegistry::Global());
    114   TF_ASSERT_OK(root.ToGraph(&g));
    115 
    116   // Perform stream assignment using a large number of streams, but with
    117   // op types constrained to specific streams.
    118   std::unordered_map<int, int> node_to_stream_id;
    119   gpu_stream_util::AssignStreamsOpts opts;
    120   opts.max_streams = 100;
    121   opts.const_stream = 90;
    122   opts.send_stream = 91;
    123   opts.recv_stream = 92;
    124   opts.compute_stream = 93;
    125   TF_ASSERT_OK(gpu_stream_util::AssignStreams(&g, opts, &node_to_stream_id));
    126 
    127   // There should be 7 nodes assigned.
    128   EXPECT_EQ(7, node_to_stream_id.size());  // including _SOURCE and _SINK
    129 
    130   // Nodes should be assigned to streams by op type.
    131   for (const auto& it : node_to_stream_id) {
    132     Node* n = g.FindNodeId(it.first);
    133     const string& op = n->type_string();
    134     const int stream = it.second;
    135     if (op == "Const") {
    136       EXPECT_EQ(stream, 90);
    137     } else if (op == "_Send") {
    138       EXPECT_EQ(stream, 91);
    139     } else if (op == "_Recv") {
    140       EXPECT_EQ(stream, 92);
    141     } else {  // Compute.
    142       EXPECT_EQ(stream, 93);
    143     }
    144   }
    145 }
    146 
    147 }  // namespace
    148 }  // namespace tensorflow
    149