prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Student T tests fail on GPU [bug]
  ```self = MultivariateStudentT(df: 1.5, loc: torch.Size([2]), scale_tril: torch.Size([2, 2]))
  sample_shape = torch.Size([])
  
      def rsample(self, sample_shape=torch.Size()):
          shape = self._extended_shape(sample_shape)
          X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()
          Z = self._chi2.rsample(sample_shape)
          Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)
  >       return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)
  E       RuntimeError: Expected object of device type cuda but got device type cpu for argument #2 'mat2' in call to _th_mm
  
  pyro/distributions/multivariate_studentt.py:74: RuntimeError
  ```
  
  This issue was discussed in #2226 - running `make test` on the dev branch errors out for me if running on a machine with cuda. I am guessing this hasn't shown up in the CI because it uses a cpu only machine. 
  
  I think this bug is pretty simple - it happens because, as we can see in the above snippet, y inherits its device from self.df, and in the fixture, self.df is set to a scalar value. This is not converted into a tensor by the tensors_default_to context manager, and so isn't sent to the gpu. 
  
  I fixed this in #2226 by changing the fixture, but @fritzo suggested that it might suggest a missing coercion rather than a change to the fixture, so that change in the PR was reverted and I am opening this issue instead.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pyro/distributions/multivariate_studentt.py`
  Content:
  ```
  1 import math
  2 
  3 import torch
  4 from torch.distributions import constraints
  5 from torch.distributions.utils import broadcast_all, lazy_property
  6 
  7 from pyro.distributions.torch import Chi2
  8 from pyro.distributions.torch_distribution import TorchDistribution
  9 from pyro.distributions.util import broadcast_shape
  10 
  11 
  12 class MultivariateStudentT(TorchDistribution):
  13     """
  14     Creates a multivariate Student's t-distribution parameterized by degree of
  15     freedom :attr:`df`, mean :attr:`loc` and scale :attr:`scale_tril`.
  16 
  17     :param ~torch.Tensor df: degrees of freedom
  18     :param ~torch.Tensor loc: mean of the distribution
  19     :param ~torch.Tensor scale_tril: scale of the distribution, which is
  20         a lower triangular matrix with positive diagonal entries
  21     """
  22     arg_constraints = {'df': constraints.positive,
  23                        'loc': constraints.real_vector,
  24                        'scale_tril': constraints.lower_cholesky}
  25     support = constraints.real_vector
  26     has_rsample = True
  27 
  28     def __init__(self, df, loc, scale_tril, validate_args=None):
  29         dim = loc.size(-1)
  30         assert scale_tril.shape[-2:] == (dim, dim)
  31         df, = broadcast_all(df)
  32         batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])
  33         event_shape = (dim,)
  34         self.df = df.expand(batch_shape)
  35         self.loc = loc
  36         self.scale_tril = scale_tril
  37         self._chi2 = Chi2(self.df)
  38         super(MultivariateStudentT, self).__init__(batch_shape, event_shape, validate_args=validate_args)
  39 
  40     @lazy_property
  41     def covariance_matrix(self):
  42         # NB: this is not covariance of this distribution;
  43         # the actual covariance is df / (df - 2) * covariance_matrix
  44         return torch.matmul(self.scale_tril, self.scale_tril.transpose(-1, -2))
  45 
  46     @lazy_property
  47     def precision_matrix(self):
  48         identity = torch.eye(self.loc.size(-1), device=self.loc.device, dtype=self.loc.dtype)
  49         scale_inv = identity.triangular_solve(self.scale_tril, upper=False).solution.transpose(-1, -2)
  50         return torch.matmul(scale_inv.transpose(-1, -2), scale_inv)
  51 
  52     def expand(self, batch_shape, _instance=None):
  53         new = self._get_checked_instance(MultivariateStudentT, _instance)
  54         batch_shape = torch.Size(batch_shape)
  55         loc_shape = batch_shape + self.event_shape
  56         scale_shape = loc_shape + self.event_shape
  57         new.df = self.df.expand(batch_shape)
  58         new.loc = self.loc.expand(loc_shape)
  59         new.scale_tril = self.scale_tril.expand(scale_shape)
  60         if 'covariance_matrix' in self.__dict__:
  61             new.covariance_matrix = self.covariance_matrix.expand(scale_shape)
  62         if 'precision_matrix' in self.__dict__:
  63             new.precision_matrix = self.precision_matrix.expand(scale_shape)
  64         new._chi2 = self._chi2.expand(batch_shape)
  65         super(MultivariateStudentT, new).__init__(batch_shape, self.event_shape, validate_args=False)
  66         new._validate_args = self._validate_args
  67         return new
  68 
  69     def rsample(self, sample_shape=torch.Size()):
  70         shape = self._extended_shape(sample_shape)
  71         X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()
  72         Z = self._chi2.rsample(sample_shape)
  73         Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)
  74         return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)
  75 
  76     def log_prob(self, value):
  77         if self._validate_args:
  78             self._validate_sample(value)
  79         n = self.loc.size(-1)
  80         y = (value - self.loc).unsqueeze(-1).triangular_solve(self.scale_tril, upper=False).solution.squeeze(-1)
  81         Z = (self.scale_tril.diagonal(dim1=-2, dim2=-1).log().sum(-1) +
  82              0.5 * n * self.df.log() +
  83              0.5 * n * math.log(math.pi) +
  84              torch.lgamma(0.5 * self.df) -
  85              torch.lgamma(0.5 * (self.df + n)))
  86         return -0.5 * (self.df + n) * torch.log1p(y.pow(2).sum(-1) / self.df) - Z
  87 
  88     @property
  89     def mean(self):
  90         m = self.loc.clone()
  91         m[self.df <= 1, :] = float('nan')
  92         return m
  93 
  94     @property
  95     def variance(self):
  96         m = self.scale_tril.pow(2).sum(-1) * (self.df / (self.df - 2)).unsqueeze(-1)
  97         m[(self.df <= 2) & (self.df > 1), :] = float('inf')
  98         m[self.df <= 1, :] = float('nan')
  99         return m
  100
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/pyro/distributions/multivariate_studentt.py b/pyro/distributions/multivariate_studentt.py
  --- a/pyro/distributions/multivariate_studentt.py
  +++ b/pyro/distributions/multivariate_studentt.py
  @@ -2,7 +2,7 @@
   
   import torch
   from torch.distributions import constraints
  -from torch.distributions.utils import broadcast_all, lazy_property
  +from torch.distributions.utils import lazy_property
   
   from pyro.distributions.torch import Chi2
   from pyro.distributions.torch_distribution import TorchDistribution
  @@ -28,7 +28,8 @@
       def __init__(self, df, loc, scale_tril, validate_args=None):
           dim = loc.size(-1)
           assert scale_tril.shape[-2:] == (dim, dim)
  -        df, = broadcast_all(df)
  +        if not isinstance(df, torch.Tensor):
  +            df = loc.new_tensor(df)
           batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])
           event_shape = (dim,)
           self.df = df.expand(batch_shape)
  
verification_info: {"golden_diff": "diff --git a/pyro/distributions/multivariate_studentt.py b/pyro/distributions/multivariate_studentt.py\n--- a/pyro/distributions/multivariate_studentt.py\n+++ b/pyro/distributions/multivariate_studentt.py\n@@ -2,7 +2,7 @@\n \n import torch\n from torch.distributions import constraints\n-from torch.distributions.utils import broadcast_all, lazy_property\n+from torch.distributions.utils import lazy_property\n \n from pyro.distributions.torch import Chi2\n from pyro.distributions.torch_distribution import TorchDistribution\n@@ -28,7 +28,8 @@\n     def __init__(self, df, loc, scale_tril, validate_args=None):\n         dim = loc.size(-1)\n         assert scale_tril.shape[-2:] == (dim, dim)\n-        df, = broadcast_all(df)\n+        if not isinstance(df, torch.Tensor):\n+            df = loc.new_tensor(df)\n         batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])\n         event_shape = (dim,)\n         self.df = df.expand(batch_shape)\n", "issue": "Student T tests fail on GPU [bug]\n```self = MultivariateStudentT(df: 1.5, loc: torch.Size([2]), scale_tril: torch.Size([2, 2]))\r\nsample_shape = torch.Size([])\r\n\r\n    def rsample(self, sample_shape=torch.Size()):\r\n        shape = self._extended_shape(sample_shape)\r\n        X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()\r\n        Z = self._chi2.rsample(sample_shape)\r\n        Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)\r\n>       return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)\r\nE       RuntimeError: Expected object of device type cuda but got device type cpu for argument #2 'mat2' in call to _th_mm\r\n\r\npyro/distributions/multivariate_studentt.py:74: RuntimeError\r\n```\r\n\r\nThis issue was discussed in #2226 - running `make test` on the dev branch errors out for me if running on a machine with cuda. I am guessing this hasn't shown up in the CI because it uses a cpu only machine. \r\n\r\nI think this bug is pretty simple - it happens because, as we can see in the above snippet, y inherits its device from self.df, and in the fixture, self.df is set to a scalar value. This is not converted into a tensor by the tensors_default_to context manager, and so isn't sent to the gpu. \r\n\r\nI fixed this in #2226 by changing the fixture, but @fritzo suggested that it might suggest a missing coercion rather than a change to the fixture, so that change in the PR was reverted and I am opening this issue instead.\r\n\n", "before_files": [{"content": "import math\n\nimport torch\nfrom torch.distributions import constraints\nfrom torch.distributions.utils import broadcast_all, lazy_property\n\nfrom pyro.distributions.torch import Chi2\nfrom pyro.distributions.torch_distribution import TorchDistribution\nfrom pyro.distributions.util import broadcast_shape\n\n\nclass MultivariateStudentT(TorchDistribution):\n    \"\"\"\n    Creates a multivariate Student's t-distribution parameterized by degree of\n    freedom :attr:`df`, mean :attr:`loc` and scale :attr:`scale_tril`.\n\n    :param ~torch.Tensor df: degrees of freedom\n    :param ~torch.Tensor loc: mean of the distribution\n    :param ~torch.Tensor scale_tril: scale of the distribution, which is\n        a lower triangular matrix with positive diagonal entries\n    \"\"\"\n    arg_constraints = {'df': constraints.positive,\n                       'loc': constraints.real_vector,\n                       'scale_tril': constraints.lower_cholesky}\n    support = constraints.real_vector\n    has_rsample = True\n\n    def __init__(self, df, loc, scale_tril, validate_args=None):\n        dim = loc.size(-1)\n        assert scale_tril.shape[-2:] == (dim, dim)\n        df, = broadcast_all(df)\n        batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])\n        event_shape = (dim,)\n        self.df = df.expand(batch_shape)\n        self.loc = loc\n        self.scale_tril = scale_tril\n        self._chi2 = Chi2(self.df)\n        super(MultivariateStudentT, self).__init__(batch_shape, event_shape, validate_args=validate_args)\n\n    @lazy_property\n    def covariance_matrix(self):\n        # NB: this is not covariance of this distribution;\n        # the actual covariance is df / (df - 2) * covariance_matrix\n        return torch.matmul(self.scale_tril, self.scale_tril.transpose(-1, -2))\n\n    @lazy_property\n    def precision_matrix(self):\n        identity = torch.eye(self.loc.size(-1), device=self.loc.device, dtype=self.loc.dtype)\n        scale_inv = identity.triangular_solve(self.scale_tril, upper=False).solution.transpose(-1, -2)\n        return torch.matmul(scale_inv.transpose(-1, -2), scale_inv)\n\n    def expand(self, batch_shape, _instance=None):\n        new = self._get_checked_instance(MultivariateStudentT, _instance)\n        batch_shape = torch.Size(batch_shape)\n        loc_shape = batch_shape + self.event_shape\n        scale_shape = loc_shape + self.event_shape\n        new.df = self.df.expand(batch_shape)\n        new.loc = self.loc.expand(loc_shape)\n        new.scale_tril = self.scale_tril.expand(scale_shape)\n        if 'covariance_matrix' in self.__dict__:\n            new.covariance_matrix = self.covariance_matrix.expand(scale_shape)\n        if 'precision_matrix' in self.__dict__:\n            new.precision_matrix = self.precision_matrix.expand(scale_shape)\n        new._chi2 = self._chi2.expand(batch_shape)\n        super(MultivariateStudentT, new).__init__(batch_shape, self.event_shape, validate_args=False)\n        new._validate_args = self._validate_args\n        return new\n\n    def rsample(self, sample_shape=torch.Size()):\n        shape = self._extended_shape(sample_shape)\n        X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()\n        Z = self._chi2.rsample(sample_shape)\n        Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)\n        return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)\n\n    def log_prob(self, value):\n        if self._validate_args:\n            self._validate_sample(value)\n        n = self.loc.size(-1)\n        y = (value - self.loc).unsqueeze(-1).triangular_solve(self.scale_tril, upper=False).solution.squeeze(-1)\n        Z = (self.scale_tril.diagonal(dim1=-2, dim2=-1).log().sum(-1) +\n             0.5 * n * self.df.log() +\n             0.5 * n * math.log(math.pi) +\n             torch.lgamma(0.5 * self.df) -\n             torch.lgamma(0.5 * (self.df + n)))\n        return -0.5 * (self.df + n) * torch.log1p(y.pow(2).sum(-1) / self.df) - Z\n\n    @property\n    def mean(self):\n        m = self.loc.clone()\n        m[self.df <= 1, :] = float('nan')\n        return m\n\n    @property\n    def variance(self):\n        m = self.scale_tril.pow(2).sum(-1) * (self.df / (self.df - 2)).unsqueeze(-1)\n        m[(self.df <= 2) & (self.df > 1), :] = float('inf')\n        m[self.df <= 1, :] = float('nan')\n        return m\n", "path": "pyro/distributions/multivariate_studentt.py"}], "after_files": [{"content": "import math\n\nimport torch\nfrom torch.distributions import constraints\nfrom torch.distributions.utils import lazy_property\n\nfrom pyro.distributions.torch import Chi2\nfrom pyro.distributions.torch_distribution import TorchDistribution\nfrom pyro.distributions.util import broadcast_shape\n\n\nclass MultivariateStudentT(TorchDistribution):\n    \"\"\"\n    Creates a multivariate Student's t-distribution parameterized by degree of\n    freedom :attr:`df`, mean :attr:`loc` and scale :attr:`scale_tril`.\n\n    :param ~torch.Tensor df: degrees of freedom\n    :param ~torch.Tensor loc: mean of the distribution\n    :param ~torch.Tensor scale_tril: scale of the distribution, which is\n        a lower triangular matrix with positive diagonal entries\n    \"\"\"\n    arg_constraints = {'df': constraints.positive,\n                       'loc': constraints.real_vector,\n                       'scale_tril': constraints.lower_cholesky}\n    support = constraints.real_vector\n    has_rsample = True\n\n    def __init__(self, df, loc, scale_tril, validate_args=None):\n        dim = loc.size(-1)\n        assert scale_tril.shape[-2:] == (dim, dim)\n        if not isinstance(df, torch.Tensor):\n            df = loc.new_tensor(df)\n        batch_shape = broadcast_shape(df.shape, loc.shape[:-1], scale_tril.shape[:-2])\n        event_shape = (dim,)\n        self.df = df.expand(batch_shape)\n        self.loc = loc\n        self.scale_tril = scale_tril\n        self._chi2 = Chi2(self.df)\n        super(MultivariateStudentT, self).__init__(batch_shape, event_shape, validate_args=validate_args)\n\n    @lazy_property\n    def covariance_matrix(self):\n        # NB: this is not covariance of this distribution;\n        # the actual covariance is df / (df - 2) * covariance_matrix\n        return torch.matmul(self.scale_tril, self.scale_tril.transpose(-1, -2))\n\n    @lazy_property\n    def precision_matrix(self):\n        identity = torch.eye(self.loc.size(-1), device=self.loc.device, dtype=self.loc.dtype)\n        scale_inv = identity.triangular_solve(self.scale_tril, upper=False).solution.transpose(-1, -2)\n        return torch.matmul(scale_inv.transpose(-1, -2), scale_inv)\n\n    def expand(self, batch_shape, _instance=None):\n        new = self._get_checked_instance(MultivariateStudentT, _instance)\n        batch_shape = torch.Size(batch_shape)\n        loc_shape = batch_shape + self.event_shape\n        scale_shape = loc_shape + self.event_shape\n        new.df = self.df.expand(batch_shape)\n        new.loc = self.loc.expand(loc_shape)\n        new.scale_tril = self.scale_tril.expand(scale_shape)\n        if 'covariance_matrix' in self.__dict__:\n            new.covariance_matrix = self.covariance_matrix.expand(scale_shape)\n        if 'precision_matrix' in self.__dict__:\n            new.precision_matrix = self.precision_matrix.expand(scale_shape)\n        new._chi2 = self._chi2.expand(batch_shape)\n        super(MultivariateStudentT, new).__init__(batch_shape, self.event_shape, validate_args=False)\n        new._validate_args = self._validate_args\n        return new\n\n    def rsample(self, sample_shape=torch.Size()):\n        shape = self._extended_shape(sample_shape)\n        X = torch.empty(shape, dtype=self.df.dtype, device=self.df.device).normal_()\n        Z = self._chi2.rsample(sample_shape)\n        Y = X * torch.rsqrt(Z / self.df).unsqueeze(-1)\n        return self.loc + self.scale_tril.matmul(Y.unsqueeze(-1)).squeeze(-1)\n\n    def log_prob(self, value):\n        if self._validate_args:\n            self._validate_sample(value)\n        n = self.loc.size(-1)\n        y = (value - self.loc).unsqueeze(-1).triangular_solve(self.scale_tril, upper=False).solution.squeeze(-1)\n        Z = (self.scale_tril.diagonal(dim1=-2, dim2=-1).log().sum(-1) +\n             0.5 * n * self.df.log() +\n             0.5 * n * math.log(math.pi) +\n             torch.lgamma(0.5 * self.df) -\n             torch.lgamma(0.5 * (self.df + n)))\n        return -0.5 * (self.df + n) * torch.log1p(y.pow(2).sum(-1) / self.df) - Z\n\n    @property\n    def mean(self):\n        m = self.loc.clone()\n        m[self.df <= 1, :] = float('nan')\n        return m\n\n    @property\n    def variance(self):\n        m = self.scale_tril.pow(2).sum(-1) * (self.df / (self.df - 2)).unsqueeze(-1)\n        m[(self.df <= 2) & (self.df > 1), :] = float('inf')\n        m[self.df <= 1, :] = float('nan')\n        return m\n", "path": "pyro/distributions/multivariate_studentt.py"}]}