You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效获取大尺寸NumPy坐标数组的对称差(含分块处理)

问题描述

我有两个超大尺寸的NumPy坐标数组,格式为[[x1,y1,z1],[x2,y2,z2]...],包含约10^9个元素。两个数组尺寸不同,坐标存在重叠(部分坐标仅存在于其中一个数组),需要快速获取所有仅存在于单个数组中的坐标。

示例代码

import numpy as np
array1 = np.array([[1,2,3],[2,3,4],[3,4,5],[4,5,6]])
array2 = np.array([[2,3,4],[3,4,5],[4,5,6],[5,6,7]])

array_diff = some_function_to_get_diff(array1,array2)

期望输出

array_diff: np.array([[1,2,3],[5,6,7]])

已知一维数组可用setdiff1d处理,但不清楚如何适配二维数组。文件大小达10GB级别,希望方案支持快速处理、分块并行。


更新内容

已测试两种实现方案,性能对比如下:

方案1:基于集合的实现

def some_faster_function_to_get_diff(array1, array2):
    unique1 = np.unique(array1, axis=0)  # 获取array1中的唯一坐标
    unique2 = np.unique(array2, axis=0)  # 获取array2中的唯一坐标

    set1 = set(map(tuple, unique1))
    set2 = set(map(tuple, unique2))

    array1_only = np.array(list(set1 - set2))
    array2_only = np.array(list(set2 - set1))

    if array1_only.size == 0:
        return array2_only
    if array2_only.size == 0:
        return array1_only

    return np.vstack((array1_only, array2_only))

方案2:基于结构化数组的实现(由@Andrés提供)

def symmetric_difference(arr1, arr2):        
    dtype = [('f{}'.format(i), arr1.dtype) for i in range(arr1.shape[1])]
    struct_arr1 = np.ascontiguousarray(arr1).view(dtype)
    struct_arr2 = np.ascontiguousarray(arr2).view(dtype)
    unique_to_arr1 = np.setdiff1d(struct_arr1, struct_arr2, assume_unique=True)
    unique_to_arr2 = np.setdiff1d(struct_arr2, struct_arr1,assume_unique=True)
    result = np.concatenate([unique_to_arr1, unique_to_arr2]).view(arr1.dtype).reshape(-1, arr1.shape[1])

    return result

性能测试代码及结果

from sys import getsizeof
import time

for i in range(2,9):
 
    no_ele=3*10**i
    arr1 = np.random.rand(no_ele, 3) * 100
    arr2 = np.random.rand(no_ele, 3) * 100

    print(f"i={i}: 内存占用 {getsizeof(arr2)/1024**3:2f}GB")
    arr2[50:60] = arr1[50:60] 
    t0=time.time()
    diff1=symmetric_difference(arr1,arr2)
    t1=time.time()
    print(f"{no_ele}: 结构化数组方案耗时 {t1-t0}")
    t0=time.time()
    diff2=some_faster_function_to_get_diff(arr1,arr2)
    t1=time.time()
    print(f"{no_ele}: 集合方案耗时 {t1-t0}")

测试输出:

i=2: 内存占用 0.000007GB
300: 结构化数组方案耗时 0.0004420280456542969
300: 集合方案耗时 0.0007300376892089844
i=3: 内存占用 0.000067GB
3000: 结构化数组方案耗时 0.0038480758666992188
3000: 集合方案耗时 0.0068819522857666016
i=4: 内存占用 0.000671GB
30000: 结构化数组方案耗时 0.052056074142456055
30000: 集合方案耗时 0.07555103302001953
i=5: 内存占用 0.006706GB
300000: 结构化数组方案耗时 0.6442217826843262
300000: 集合方案耗时 0.9859399795532227
i=6: 内存占用 0.067055GB
3000000: 结构化数组方案耗时 9.833515882492065
3000000: 集合方案耗时 12.196370840072632
i=7: 内存占用 0.670552GB
30000000: 结构化数组方案耗时 142.16755604743958
30000000: 集合方案耗时 138.87937593460083

测试结论:两种方案均可行,结构化数组方案在数据量较小时更快;当数据量达到千万级后,集合方案性能反超,整体性能相近。


新问题

当前数组无法放入内存,已知laspy包支持分块读取数据(示例代码如下),寻求基于分块读取的解决方案:

with laspy.open(las_file1) as f1, laspy.open(las_file2) as f2:
    for points1 in f1.chunk_iterator(chunk_size):
        # 处理逻辑

内容的提问来源于stack exchange,提问作者abinitio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 03:45:01