docs: def _linux_gpu_data():
      '''
      num_gpus: int
      gpus:
        - vendor: nvidia|amd|ati|...
          model: string
      '''
      if __opts__.get('enable_lspci', True) is False:
          return {}
  
      if __opts__.get('enable_gpu_grains', True) is False:
          return {}
  
      lspci = salt.utils.path.which('lspci')
      if not lspci:
          log.debug(
              'The `lspci` binary is not available on the system. GPU grains '
              'will not be available.'
          )
          return {}
  
      # dominant gpu vendors to search for (MUST be lowercase for matching below)
      known_vendors = ['nvidia', 'amd', 'ati', 'intel', 'cirrus logic', 'vmware', 'matrox', 'aspeed']
      gpu_classes = ('vga compatible controller', '3d controller')
  
      devs = []
      try:
          lspci_out = __salt__['cmd.run']('{0} -vmm'.format(lspci))
  
          cur_dev = {}
          error = False
          # Add a blank element to the lspci_out.splitlines() list,
          # otherwise the last device is not evaluated as a cur_dev and ignored.
          lspci_list = lspci_out.splitlines()
          lspci_list.append('')
          for line in lspci_list:
              # check for record-separating empty lines
              if line == '':
                  if cur_dev.get('Class', '').lower() in gpu_classes:
                      devs.append(cur_dev)
                  cur_dev = {}
                  continue
              if re.match(r'^\w+:\s+.*', line):
                  key, val = line.split(':', 1)
                  cur_dev[key.strip()] = val.strip()
              else:
                  error = True
                  log.debug('Unexpected lspci output: \'%s\'', line)
  
          if error:
              log.warning(
                  'Error loading grains, unexpected linux_gpu_data output, '
                  'check that you have a valid shell configured and '
                  'permissions to run lspci command'
              )
      except OSError:
          pass
  
      gpus = []
      for gpu in devs:
          vendor_strings = re.split('[^A-Za-z0-9]', gpu['Vendor'].lower())
          # default vendor to 'unknown', overwrite if we match a known one
          vendor = 'unknown'
          for name in known_vendors:
              # search for an 'expected' vendor name in the list of strings
              if name in vendor_strings:
                  vendor = name
                  break
          gpus.append({'vendor': vendor, 'model': gpu['Device']})
  
      grains = {}
      grains['num_gpus'] = len(gpus)
      grains['gpus'] = gpus
      return grains