计算一个大的 haversine 距离矩阵

Calculating a large haversine distance matrix

运行 OOM 试图计算地理坐标列表上的半正弦距离矩阵。我可以访问适合距离矩阵的 GPU,但我找不到任何具有为 GPU 实现的半正弦距离矩阵的库。寻找为此编写 CUDA 内核的建议。

阅读 numba 的 cuda 库和 NVIDIA Rapids 后,我能够创建以下 Python 函数:

from numba import cuda
import math

@cuda.jit
def gpu_haversine_distance_matrix(lon, lat, dm):
  i,j = cuda.grid(2)
  if i < lon.shape[0] == dm.shape[0] and j < lat.shape[0] == dm.shape[1]:
    if i == j:
      dm[i][j] = 0
    else:
      if i < j:
        longit_a = math.radians(lon[i])
        latit_a = math.radians(lat[i])
        longit_b = math.radians(lon[j])
        latit_b =  math.radians(lat[j])
      else:
        longit_a = math.radians(lon[j])
        latit_a = math.radians(lat[j])
        longit_b = math.radians(lon[i])
        latit_b =  math.radians(lat[i])
        
      dist_longit_add = longit_b - longit_a
      dist_latit_sub = latit_b - latit_a
      dist_latit_add = latit_b + latit_a
      pre_comp = math.sin(dist_latit_sub/2)**2
      area = pre_comp + ((1 - pre_comp - math.sin(dist_latit_add/2)**2) * math.sin(dist_longit_add/2)**2)
      central_angle = 2 * math.asin(math.sqrt(area))
      radius = 3958
      dm[i][j] = math.fabs(central_angle * radius)

co_loc_cdf = cudf.from_pandas(co_loc) # pandas dataframe containing longitude and latitude column
dm_global_mem = cuda.device_array((co_loc_cdf.shape[0], co_loc_cdf.shape[0]))

threadsperblock = (16, 16)
blockspergrid_x = math.ceil(co_loc_cdf.shape[0] / threadsperblock[0])
blockspergrid_y = math.ceil(co_loc_cdf.shape[0] / threadsperblock[0])
blockspergrid = (blockspergrid_x, blockspergrid_y)
haversine_gpu_distance_matrix[blockspergrid, threadsperblock](co_loc_cdf['longitude'], co_loc_cdf['latitude'], dm_global_mem)

这 return 是 GPU 内存中的半正弦距离矩阵。距离单位以英里为单位,但如果需要,可以将 radius 值调整为 return 米。仍然希望了解如何最好地决定每个块的线程数和每个网格的块数。