code: def train_kmeans(x, k, ngpu, max_points_per_centroid=256):
      "Runs kmeans on one or several GPUs"
      d = x.shape[1]
      clus = faiss.Clustering(d, k)
      clus.verbose = True
      clus.niter = 20
      clus.max_points_per_centroid = max_points_per_centroid
  
      if ngpu == 0:
          index = faiss.IndexFlatL2(d)
      else:
          res = [faiss.StandardGpuResources() for i in range(ngpu)]
  
          flat_config = []
          for i in range(ngpu):
              cfg = faiss.GpuIndexFlatConfig()
              cfg.useFloat16 = False
              cfg.device = i
              flat_config.append(cfg)
  
          if ngpu == 1:
              index = faiss.GpuIndexFlatL2(res[0], d, flat_config[0])
          else:
              indexes = [
                  faiss.GpuIndexFlatL2(res[i], d, flat_config[i])
                  for i in range(ngpu)
              ]
              index = faiss.IndexReplicas()
              for sub_index in indexes:
                  index.addIndex(sub_index)
  
      # perform the training
      clus.train(x, index)
      centroids = faiss.vector_float_to_array(clus.centroids)
  
      stats = clus.iteration_stats
      stats = [stats.at(i) for i in range(stats.size())]
      obj = np.array([st.obj for st in stats])
      print("final objective: %.4g" % obj[-1])
  
      return centroids.reshape(k, d)
  
file_path: faiss/benchs/link_and_code/neighbor_codec.py
imports: from __future__ import print_function
  import time
  import numpy
  import faiss
label_desc: Use image node_id 2 for calling a global function with example usage: train_kmeans(x, k, ngpu, max_points_per_centroid) and returns: centroids