{"action":"created","comment":{"url":"https://api.github.com/repos/pytorch/pytorch/pulls/comments/188817053","pull_request_review_id":120864014,"id":188817053,"diff_hunk":"@@ -0,0 +1,390 @@\n+#include \"ProcessGroupGloo.hpp\"\n+\n+#include <gloo/allreduce_halving_doubling.h>\n+#include <gloo/rendezvous/context.h>\n+\n+#define GENERATE_ALL_TYPES(type, func, args...)                         \\\n+  switch (type) {                                                       \\\n+    case ::at::ScalarType::Float: func<float>(args); break;             \\\n+    case ::at::ScalarType::Double: func<double>(args); break;           \\\n+    case ::at::ScalarType::Half: func<gloo::float16>(args); break;      \\\n+    case ::at::ScalarType::Char: func<int8_t>(args); break;             \\\n+    case ::at::ScalarType::Byte: func<uint8_t>(args); break;            \\\n+    case ::at::ScalarType::Int: func<int32_t>(args); break;             \\\n+    case ::at::ScalarType::Long: func<int64_t>(args); break;            \\\n+    default:                                                            \\\n+      throw std::runtime_error(\"Invalid scalar type\");                  \\\n+  }\n+\n+namespace c10d {\n+\n+using KeyType = AlgorithmKey;\n+using EntryType = std::unique_ptr<AlgorithmEntry>;\n+\n+namespace {\n+\n+// Wrap c10d store as Gloo store\n+class GlooStore : public ::gloo::rendezvous::Store {\n+ public:\n+  GlooStore(const std::shared_ptr<::c10d::Store>& store)\n+      : store_(store) {\n+  }\n+\n+  void set(const std::string& key, const std::vector<char>& value) override {\n+    // @pietern was unable to figure out a way to cast the value of\n+    // type std::vector<char> to an std::vector<unsigned char>,\n+    // so going with a copy here (it's not a hot path so it's fine).\n+    std::vector<uint8_t> tmp(value.size());\n+    memcpy(tmp.data(), value.data(), value.size());\n+    store_->set(key, tmp);\n+  }\n+\n+  std::vector<char> get(const std::string& key) override {\n+    // @pietern was unable to figure out a way to cast the value of\n+    // type std::vector<unsigned char> to an std::vector<char>,\n+    // so going with a copy here (it's not a hot path so it's fine).\n+    auto value = store_->get(key);\n+    std::vector<char> tmp(value.size());\n+    memcpy(tmp.data(), value.data(), value.size());\n+    return tmp;\n+  }\n+\n+  void wait(const std::vector<std::string>& keys) override {\n+    store_->wait(keys, Store::kDefaultTimeout);\n+  }\n+\n+  void wait(\n+      const std::vector<std::string>& keys,\n+      const std::chrono::milliseconds& timeout) override {\n+    store_->wait(keys, timeout);\n+  }\n+\n+ protected:\n+  std::shared_ptr<::c10d::Store> store_;\n+};\n+\n+template <typename T>\n+const ::gloo::ReductionFunction<T>* reductionFunction(const ReduceOp& r) {\n+  switch (r) {\n+    case ReduceOp::SUM:\n+      return ::gloo::ReductionFunction<T>::sum;\n+    case ReduceOp::PRODUCT:\n+      return ::gloo::ReductionFunction<T>::product;\n+    case ReduceOp::MIN:\n+      return ::gloo::ReductionFunction<T>::min;\n+    case ReduceOp::MAX:\n+      return ::gloo::ReductionFunction<T>::max;\n+  }\n+\n+  throw std::runtime_error(\"Unhandled ReduceOp\");\n+}\n+\n+} // namespace\n+\n+ProcessGroupGloo::WorkGloo::WorkGloo() {\n+  completed_ = false;\n+}\n+\n+ProcessGroupGloo::WorkGloo::~WorkGloo() {\n+}\n+\n+bool ProcessGroupGloo::WorkGloo::isCompleted() {\n+  std::unique_lock<std::mutex> lock(m_);\n+  return completed_;\n+}\n+\n+bool ProcessGroupGloo::WorkGloo::wait() {\n+  std::unique_lock<std::mutex> lock(m_);\n+  while (!completed_) {\n+    cv_.wait(lock);\n+  }\n+  return !ex_;\n+}\n+\n+const std::exception& ProcessGroupGloo::WorkGloo::exception() const {\n+  return *ex_;\n+}\n+\n+void ProcessGroupGloo::WorkGloo::finish() {\n+  {\n+    std::unique_lock<std::mutex> lock(m_);\n+    completed_ = true;\n+  }\n+  cv_.notify_all();\n+}\n+\n+void ProcessGroupGloo::WorkGloo::finishWithException(\n+    const ::gloo::Exception& ex) {\n+  {\n+    std::unique_lock<std::mutex> lock(m_);\n+    completed_ = true;\n+    ex_ = std::unique_ptr<::gloo::Exception>(new ::gloo::Exception(ex));\n+  }\n+  cv_.notify_all();\n+}\n+\n+ProcessGroupGloo::ProcessGroupGloo(\n+    const std::shared_ptr<Store>& store,\n+    const std::vector<std::shared_ptr<::gloo::transport::Device>>& devices,\n+    int rank,\n+    int size)\n+    : ProcessGroup(rank, size),\n+      store_(new GlooStore(store)),\n+      devices_(devices) {\n+  stop_ = false;\n+}\n+\n+ProcessGroupGloo::~ProcessGroupGloo() {\n+  // Require this process group to be explicitly shut down prior to being\n+  // destructed. This is the easiest way to guarantee clean shutdown\n+  // and avoid blocking/throwing in a destructor.\n+}\n+\n+void ProcessGroupGloo::initialize() {\n+  contexts_.clear();\n+  for (auto& device : devices_) {\n+    auto context = std::shared_ptr<::gloo::rendezvous::Context>(\n+        new ::gloo::rendezvous::Context(rank_, size_));\n+    context->setTimeout(std::chrono::milliseconds(100));\n+    context->connectFullMesh(*store_, device);\n+    contexts_.push_back(std::move(context));\n+  }\n+\n+  // TODO(@pietern): Make number of threads configurable\n+  threads_.resize(2);\n+  for (int i = 0; i < threads_.size(); i++) {\n+    threads_[i] = std::thread(&ProcessGroupGloo::runLoop, this);\n+  }\n+}\n+\n+void ProcessGroupGloo::destroy() {\n+  std::unique_lock<std::mutex> lock(m_);\n+  while (!queue_.empty()) {\n+    queueConsumeCV_.wait(lock);\n+  }\n+\n+  // Queue is empty, signal stop\n+  stop_ = true;\n+\n+  // Release lock to allow threads to terminate\n+  queueProduceCV_.notify_all();\n+  lock.unlock();\n+\n+  // Wait for worker threads to terminate\n+  for (auto& thread : threads_) {\n+    thread.join();\n+  }\n+}\n+\n+void ProcessGroupGloo::runLoop(void) {\n+  std::unique_lock<std::mutex> lock(m_);\n+\n+  while (!stop_) {\n+    if (queue_.empty()) {\n+      queueProduceCV_.wait(lock);\n+      continue;\n+    }\n+\n+    auto tuple = std::move(queue_.front());","path":"torch/lib/c10d/ProcessGroupGloo.cpp","position":188,"original_position":188,"commit_id":"eed8b1e7d7febb5d1c6cc9eef757290ff957bd7f","original_commit_id":"eed8b1e7d7febb5d1c6cc9eef757290ff957bd7f","user":{"login":"teng-li","id":8120856,"avatar_url":"https://avatars2.githubusercontent.com/u/8120856?v=4","gravatar_id":"","url":"https://api.github.com/users/teng-li","html_url":"https://github.com/teng-li","followers_url":"https://api.github.com/users/teng-li/followers","following_url":"https://api.github.com/users/teng-li/following{/other_user}","gists_url":"https://api.github.com/users/teng-li/gists{/gist_id}","starred_url":"https://api.github.com/users/teng-li/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/teng-li/subscriptions","organizations_url":"https://api.github.com/users/teng-li/orgs","repos_url":"https://api.github.com/users/teng-li/repos","events_url":"https://api.github.com/users/teng-li/events{/privacy}","received_events_url":"https://api.github.com/users/teng-li/received_events","type":"User","site_admin":false},"body":"Can also use std::tie to unpack this tuple directly instead of getting them one by one ","created_at":"2018-05-17T01:25:51Z","updated_at":"2018-05-17T01:35:00Z","html_url":"https://github.com/pytorch/pytorch/pull/7628#discussion_r188817053","pull_request_url":"https://api.github.com/repos/pytorch/pytorch/pulls/7628","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/pytorch/pytorch/pulls/comments/188817053"},"html":{"href":"https://github.com/pytorch/pytorch/pull/7628#discussion_r188817053"},"pull_request":{"href":"https://api.github.com/repos/pytorch/pytorch/pulls/7628"}}},"pull_request":{"url":"https://api.github.com/repos/pytorch/pytorch/pulls/7628","id":188568990,"html_url":"https://github.com/pytorch/pytorch/pull/7628","diff_url":"https://github.com/pytorch/pytorch/pull/7628.diff","patch_url":"https://github.com/pytorch/pytorch/pull/7628.patch","issue_url":"https://api.github.com/repos/pytorch/pytorch/issues/7628","number":7628,"state":"open","locked":false,"title":"[c10d][wip] Process group base class and gloo implementation","user":{"login":"pietern","id":9845,"avatar_url":"https://avatars3.githubusercontent.com/u/9845?v=4","gravatar_id":"","url":"https://api.github.com/users/pietern","html_url":"https://github.com/pietern","followers_url":"https://api.github.com/users/pietern/followers","following_url":"https://api.github.com/users/pietern/following{/other_user}","gists_url":"https://api.github.com/users/pietern/gists{/gist_id}","starred_url":"https://api.github.com/users/pietern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pietern/subscriptions","organizations_url":"https://api.github.com/users/pietern/orgs","repos_url":"https://api.github.com/users/pietern/repos","events_url":"https://api.github.com/users/pietern/events{/privacy}","received_events_url":"https://api.github.com/users/pietern/received_events","type":"User","site_admin":false},"body":"Creating this PR as a starting point.\r\n\r\nStill need to:\r\n[ ] Describe the cache behavior in the commit message\r\n[ ] Add correctness test\r\n","created_at":"2018-05-16T21:41:36Z","updated_at":"2018-05-17T01:35:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dd2e4e9eb4b0e8ff4e44f12ae5b8ecfa84737dd4","assignee":null,"assignees":[],"requested_reviewers":[{"login":"ezyang","id":13564,"avatar_url":"https://avatars0.githubusercontent.com/u/13564?v=4","gravatar_id":"","url":"https://api.github.com/users/ezyang","html_url":"https://github.com/ezyang","followers_url":"https://api.github.com/users/ezyang/followers","following_url":"https://api.github.com/users/ezyang/following{/other_user}","gists_url":"https://api.github.com/users/ezyang/gists{/gist_id}","starred_url":"https://api.github.com/users/ezyang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ezyang/subscriptions","organizations_url":"https://api.github.com/users/ezyang/orgs","repos_url":"https://api.github.com/users/ezyang/repos","events_url":"https://api.github.com/users/ezyang/events{/privacy}","received_events_url":"https://api.github.com/users/ezyang/received_events","type":"User","site_admin":false},{"login":"zdevito","id":370202,"avatar_url":"https://avatars0.githubusercontent.com/u/370202?v=4","gravatar_id":"","url":"https://api.github.com/users/zdevito","html_url":"https://github.com/zdevito","followers_url":"https://api.github.com/users/zdevito/followers","following_url":"https://api.github.com/users/zdevito/following{/other_user}","gists_url":"https://api.github.com/users/zdevito/gists{/gist_id}","starred_url":"https://api.github.com/users/zdevito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zdevito/subscriptions","organizations_url":"https://api.github.com/users/zdevito/orgs","repos_url":"https://api.github.com/users/zdevito/repos","events_url":"https://api.github.com/users/zdevito/events{/privacy}","received_events_url":"https://api.github.com/users/zdevito/received_events","type":"User","site_admin":false},{"login":"colesbury","id":655866,"avatar_url":"https://avatars1.githubusercontent.com/u/655866?v=4","gravatar_id":"","url":"https://api.github.com/users/colesbury","html_url":"https://github.com/colesbury","followers_url":"https://api.github.com/users/colesbury/followers","following_url":"https://api.github.com/users/colesbury/following{/other_user}","gists_url":"https://api.github.com/users/colesbury/gists{/gist_id}","starred_url":"https://api.github.com/users/colesbury/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/colesbury/subscriptions","organizations_url":"https://api.github.com/users/colesbury/orgs","repos_url":"https://api.github.com/users/colesbury/repos","events_url":"https://api.github.com/users/colesbury/events{/privacy}","received_events_url":"https://api.github.com/users/colesbury/received_events","type":"User","site_admin":false},{"login":"soumith","id":1310570,"avatar_url":"https://avatars0.githubusercontent.com/u/1310570?v=4","gravatar_id":"","url":"https://api.github.com/users/soumith","html_url":"https://github.com/soumith","followers_url":"https://api.github.com/users/soumith/followers","following_url":"https://api.github.com/users/soumith/following{/other_user}","gists_url":"https://api.github.com/users/soumith/gists{/gist_id}","starred_url":"https://api.github.com/users/soumith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/soumith/subscriptions","organizations_url":"https://api.github.com/users/soumith/orgs","repos_url":"https://api.github.com/users/soumith/repos","events_url":"https://api.github.com/users/soumith/events{/privacy}","received_events_url":"https://api.github.com/users/soumith/received_events","type":"User","site_admin":false},{"login":"gchanan","id":3768583,"avatar_url":"https://avatars2.githubusercontent.com/u/3768583?v=4","gravatar_id":"","url":"https://api.github.com/users/gchanan","html_url":"https://github.com/gchanan","followers_url":"https://api.github.com/users/gchanan/followers","following_url":"https://api.github.com/users/gchanan/following{/other_user}","gists_url":"https://api.github.com/users/gchanan/gists{/gist_id}","starred_url":"https://api.github.com/users/gchanan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gchanan/subscriptions","organizations_url":"https://api.github.com/users/gchanan/orgs","repos_url":"https://api.github.com/users/gchanan/repos","events_url":"https://api.github.com/users/gchanan/events{/privacy}","received_events_url":"https://api.github.com/users/gchanan/received_events","type":"User","site_admin":false},{"login":"apaszke","id":4583066,"avatar_url":"https://avatars3.githubusercontent.com/u/4583066?v=4","gravatar_id":"","url":"https://api.github.com/users/apaszke","html_url":"https://github.com/apaszke","followers_url":"https://api.github.com/users/apaszke/followers","following_url":"https://api.github.com/users/apaszke/following{/other_user}","gists_url":"https://api.github.com/users/apaszke/gists{/gist_id}","starred_url":"https://api.github.com/users/apaszke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apaszke/subscriptions","organizations_url":"https://api.github.com/users/apaszke/orgs","repos_url":"https://api.github.com/users/apaszke/repos","events_url":"https://api.github.com/users/apaszke/events{/privacy}","received_events_url":"https://api.github.com/users/apaszke/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":679953883,"url":"https://api.github.com/repos/pytorch/pytorch/labels/distributed","name":"distributed","color":"c2e0c6","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/pytorch/pytorch/pulls/7628/commits","review_comments_url":"https://api.github.com/repos/pytorch/pytorch/pulls/7628/comments","review_comment_url":"https://api.github.com/repos/pytorch/pytorch/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pytorch/pytorch/issues/7628/comments","statuses_url":"https://api.github.com/repos/pytorch/pytorch/statuses/eed8b1e7d7febb5d1c6cc9eef757290ff957bd7f","head":{"label":"pietern:c10d-process-group","ref":"c10d-process-group","sha":"eed8b1e7d7febb5d1c6cc9eef757290ff957bd7f","user":{"login":"pietern","id":9845,"avatar_url":"https://avatars3.githubusercontent.com/u/9845?v=4","gravatar_id":"","url":"https://api.github.com/users/pietern","html_url":"https://github.com/pietern","followers_url":"https://api.github.com/users/pietern/followers","following_url":"https://api.github.com/users/pietern/following{/other_user}","gists_url":"https://api.github.com/users/pietern/gists{/gist_id}","starred_url":"https://api.github.com/users/pietern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pietern/subscriptions","organizations_url":"https://api.github.com/users/pietern/orgs","repos_url":"https://api.github.com/users/pietern/repos","events_url":"https://api.github.com/users/pietern/events{/privacy}","received_events_url":"https://api.github.com/users/pietern/received_events","type":"User","site_admin":false},"repo":{"id":110084434,"name":"pytorch","full_name":"pietern/pytorch","owner":{"login":"pietern","id":9845,"avatar_url":"https://avatars3.githubusercontent.com/u/9845?v=4","gravatar_id":"","url":"https://api.github.com/users/pietern","html_url":"https://github.com/pietern","followers_url":"https://api.github.com/users/pietern/followers","following_url":"https://api.github.com/users/pietern/following{/other_user}","gists_url":"https://api.github.com/users/pietern/gists{/gist_id}","starred_url":"https://api.github.com/users/pietern/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pietern/subscriptions","organizations_url":"https://api.github.com/users/pietern/orgs","repos_url":"https://api.github.com/users/pietern/repos","events_url":"https://api.github.com/users/pietern/events{/privacy}","received_events_url":"https://api.github.com/users/pietern/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pietern/pytorch","description":"Tensors and Dynamic neural networks in Python  with strong GPU acceleration","fork":true,"url":"https://api.github.com/repos/pietern/pytorch","forks_url":"https://api.github.com/repos/pietern/pytorch/forks","keys_url":"https://api.github.com/repos/pietern/pytorch/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pietern/pytorch/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pietern/pytorch/teams","hooks_url":"https://api.github.com/repos/pietern/pytorch/hooks","issue_events_url":"https://api.github.com/repos/pietern/pytorch/issues/events{/number}","events_url":"https://api.github.com/repos/pietern/pytorch/events","assignees_url":"https://api.github.com/repos/pietern/pytorch/assignees{/user}","branches_url":"https://api.github.com/repos/pietern/pytorch/branches{/branch}","tags_url":"https://api.github.com/repos/pietern/pytorch/tags","blobs_url":"https://api.github.com/repos/pietern/pytorch/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pietern/pytorch/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pietern/pytorch/git/refs{/sha}","trees_url":"https://api.github.com/repos/pietern/pytorch/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pietern/pytorch/statuses/{sha}","languages_url":"https://api.github.com/repos/pietern/pytorch/languages","stargazers_url":"https://api.github.com/repos/pietern/pytorch/stargazers","contributors_url":"https://api.github.com/repos/pietern/pytorch/contributors","subscribers_url":"https://api.github.com/repos/pietern/pytorch/subscribers","subscription_url":"https://api.github.com/repos/pietern/pytorch/subscription","commits_url":"https://api.github.com/repos/pietern/pytorch/commits{/sha}","git_commits_url":"https://api.github.com/repos/pietern/pytorch/git/commits{/sha}","comments_url":"https://api.github.com/repos/pietern/pytorch/comments{/number}","issue_comment_url":"https://api.github.com/repos/pietern/pytorch/issues/comments{/number}","contents_url":"https://api.github.com/repos/pietern/pytorch/contents/{+path}","compare_url":"https://api.github.com/repos/pietern/pytorch/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pietern/pytorch/merges","archive_url":"https://api.github.com/repos/pietern/pytorch/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pietern/pytorch/downloads","issues_url":"https://api.github.com/repos/pietern/pytorch/issues{/number}","pulls_url":"https://api.github.com/repos/pietern/pytorch/pulls{/number}","milestones_url":"https://api.github.com/repos/pietern/pytorch/milestones{/number}","notifications_url":"https://api.github.com/repos/pietern/pytorch/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pietern/pytorch/labels{/name}","releases_url":"https://api.github.com/repos/pietern/pytorch/releases{/id}","deployments_url":"https://api.github.com/repos/pietern/pytorch/deployments","created_at":"2017-11-09T07:53:28Z","updated_at":"2017-11-09T07:53:33Z","pushed_at":"2018-05-16T21:39:45Z","git_url":"git://github.com/pietern/pytorch.git","ssh_url":"git@github.com:pietern/pytorch.git","clone_url":"https://github.com/pietern/pytorch.git","svn_url":"https://github.com/pietern/pytorch","homepage":"http://pytorch.org","size":55132,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"pytorch:master","ref":"master","sha":"8f6f43f5cf1f9b9fed3deb7c61529f27c038b0a5","user":{"login":"pytorch","id":21003710,"avatar_url":"https://avatars3.githubusercontent.com/u/21003710?v=4","gravatar_id":"","url":"https://api.github.com/users/pytorch","html_url":"https://github.com/pytorch","followers_url":"https://api.github.com/users/pytorch/followers","following_url":"https://api.github.com/users/pytorch/following{/other_user}","gists_url":"https://api.github.com/users/pytorch/gists{/gist_id}","starred_url":"https://api.github.com/users/pytorch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pytorch/subscriptions","organizations_url":"https://api.github.com/users/pytorch/orgs","repos_url":"https://api.github.com/users/pytorch/repos","events_url":"https://api.github.com/users/pytorch/events{/privacy}","received_events_url":"https://api.github.com/users/pytorch/received_events","type":"Organization","site_admin":false},"repo":{"id":65600975,"name":"pytorch","full_name":"pytorch/pytorch","owner":{"login":"pytorch","id":21003710,"avatar_url":"https://avatars3.githubusercontent.com/u/21003710?v=4","gravatar_id":"","url":"https://api.github.com/users/pytorch","html_url":"https://github.com/pytorch","followers_url":"https://api.github.com/users/pytorch/followers","following_url":"https://api.github.com/users/pytorch/following{/other_user}","gists_url":"https://api.github.com/users/pytorch/gists{/gist_id}","starred_url":"https://api.github.com/users/pytorch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pytorch/subscriptions","organizations_url":"https://api.github.com/users/pytorch/orgs","repos_url":"https://api.github.com/users/pytorch/repos","events_url":"https://api.github.com/users/pytorch/events{/privacy}","received_events_url":"https://api.github.com/users/pytorch/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pytorch/pytorch","description":"Tensors and Dynamic neural networks in Python  with strong GPU acceleration","fork":false,"url":"https://api.github.com/repos/pytorch/pytorch","forks_url":"https://api.github.com/repos/pytorch/pytorch/forks","keys_url":"https://api.github.com/repos/pytorch/pytorch/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pytorch/pytorch/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pytorch/pytorch/teams","hooks_url":"https://api.github.com/repos/pytorch/pytorch/hooks","issue_events_url":"https://api.github.com/repos/pytorch/pytorch/issues/events{/number}","events_url":"https://api.github.com/repos/pytorch/pytorch/events","assignees_url":"https://api.github.com/repos/pytorch/pytorch/assignees{/user}","branches_url":"https://api.github.com/repos/pytorch/pytorch/branches{/branch}","tags_url":"https://api.github.com/repos/pytorch/pytorch/tags","blobs_url":"https://api.github.com/repos/pytorch/pytorch/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pytorch/pytorch/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pytorch/pytorch/git/refs{/sha}","trees_url":"https://api.github.com/repos/pytorch/pytorch/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pytorch/pytorch/statuses/{sha}","languages_url":"https://api.github.com/repos/pytorch/pytorch/languages","stargazers_url":"https://api.github.com/repos/pytorch/pytorch/stargazers","contributors_url":"https://api.github.com/repos/pytorch/pytorch/contributors","subscribers_url":"https://api.github.com/repos/pytorch/pytorch/subscribers","subscription_url":"https://api.github.com/repos/pytorch/pytorch/subscription","commits_url":"https://api.github.com/repos/pytorch/pytorch/commits{/sha}","git_commits_url":"https://api.github.com/repos/pytorch/pytorch/git/commits{/sha}","comments_url":"https://api.github.com/repos/pytorch/pytorch/comments{/number}","issue_comment_url":"https://api.github.com/repos/pytorch/pytorch/issues/comments{/number}","contents_url":"https://api.github.com/repos/pytorch/pytorch/contents/{+path}","compare_url":"https://api.github.com/repos/pytorch/pytorch/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pytorch/pytorch/merges","archive_url":"https://api.github.com/repos/pytorch/pytorch/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pytorch/pytorch/downloads","issues_url":"https://api.github.com/repos/pytorch/pytorch/issues{/number}","pulls_url":"https://api.github.com/repos/pytorch/pytorch/pulls{/number}","milestones_url":"https://api.github.com/repos/pytorch/pytorch/milestones{/number}","notifications_url":"https://api.github.com/repos/pytorch/pytorch/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pytorch/pytorch/labels{/name}","releases_url":"https://api.github.com/repos/pytorch/pytorch/releases{/id}","deployments_url":"https://api.github.com/repos/pytorch/pytorch/deployments","created_at":"2016-08-13T05:26:41Z","updated_at":"2018-05-17T01:30:10Z","pushed_at":"2018-05-17T01:24:29Z","git_url":"git://github.com/pytorch/pytorch.git","ssh_url":"git@github.com:pytorch/pytorch.git","clone_url":"https://github.com/pytorch/pytorch.git","svn_url":"https://github.com/pytorch/pytorch","homepage":"http://pytorch.org","size":55169,"stargazers_count":15525,"watchers_count":15525,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3489,"mirror_url":null,"archived":false,"open_issues_count":1084,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":3489,"open_issues":1084,"watchers":15525,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pytorch/pytorch/pulls/7628"},"html":{"href":"https://github.com/pytorch/pytorch/pull/7628"},"issue":{"href":"https://api.github.com/repos/pytorch/pytorch/issues/7628"},"comments":{"href":"https://api.github.com/repos/pytorch/pytorch/issues/7628/comments"},"review_comments":{"href":"https://api.github.com/repos/pytorch/pytorch/pulls/7628/comments"},"review_comment":{"href":"https://api.github.com/repos/pytorch/pytorch/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pytorch/pytorch/pulls/7628/commits"},"statuses":{"href":"https://api.github.com/repos/pytorch/pytorch/statuses/eed8b1e7d7febb5d1c6cc9eef757290ff957bd7f"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"teng-li"}}