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

如何用NumPy向量化优化随机瓦片地图生成算法?

基于NumPy的瓦片地图生成性能优化方案

核心优化思路

放弃逐个调用check_tile的标量处理逻辑,转而用NumPy的批量数组操作完成边界瓦片的邻域统计、概率计算和子瓦片生成,彻底消除Python循环带来的性能开销。


具体实现步骤

1. 初始网格定义

用布尔数组表示地图:True为陆地,False为水域(可根据需求调整映射关系),直接通过NumPy生成初始网格:

import numpy as np

# 初始化4x4全陆地网格,可选加入随机初始水域
map_grid = np.ones((4, 4), dtype=bool)
map_grid[np.random.rand(4,4) < 0.1] = False

2. 批量标记边界瓦片

边界瓦片定义为邻接至少一个水域的陆地瓦片,用NumPy卷积操作批量计算所有瓦片的邻域水域数量,快速标记边界:

def get_border_tiles(grid):
    # 3x3邻域掩码,排除自身
    kernel = np.ones((3,3), dtype=int)
    kernel[1,1] = 0
    
    # 批量计算每个瓦片的邻域水域数(水域用1-grid转换为1标记)
    neighbor_water_count = np.convolve((1-grid).flatten(), kernel.flatten(), mode='same').reshape(grid.shape)
    
    # 生成边界瓦片掩码:陆地且邻接水域
    border_mask = grid & (neighbor_water_count > 0)
    # 返回边界瓦片的坐标数组(每行对应(i,j))
    return np.argwhere(border_mask)

3. 向量化处理边界瓦片的细分与转换

跳过逐个处理瓦片的逻辑,直接批量完成网格放大、边界瓦片的概率计算和子瓦片生成:

def upscale_and_process_borders(grid, target_size):
    while grid.shape[0] < target_size:
        current_size = grid.shape[0]
        # 快速生成放大后的网格:每个原瓦片拆分为2x2子瓦片,默认继承原类型
        upscale_grid = np.repeat(np.repeat(grid, 2, axis=0), 2, axis=1)
        
        border_coords = get_border_tiles(grid)
        if len(border_coords) == 0:
            break
        
        # 批量获取所有边界瓦片的邻域水域数(消除循环的优化版)
        full_water_counts = get_full_neighbor_water_counts(grid)
        neighbor_water_counts = full_water_counts[tuple(border_coords.T)]
        
        # 计算子瓦片转为水域的概率(示例公式:邻接水域数/8,可自定义)
        convert_probs = neighbor_water_counts / 8.0
        
        # 批量生成随机判断结果:每个边界瓦片对应4个子瓦片
        rand_vals = np.random.rand(len(border_coords), 4)
        convert_mask = rand_vals < convert_probs[:, np.newaxis]
        
        # 批量更新放大后的网格
        for idx, (i,j) in enumerate(border_coords):
            # 原瓦片对应的4个子瓦片坐标
            upscale_pos = [
                (2*i, 2*j), (2*i, 2*j+1),
                (2*i+1, 2*j), (2*i+1, 2*j+1)
            ]
            for k, (y,x) in enumerate(upscale_pos):
                if convert_mask[idx,k]:
                    upscale_grid[y,x] = False
        
        grid = upscale_grid
    return grid

# 纯NumPy实现的全网格邻域水域数计算(消除所有循环)
def get_full_neighbor_water_counts(grid):
    current_size = grid.shape[0]
    water_counts = np.zeros(grid.shape, dtype=int)
    
    # 处理内部瓦片(3x3完整邻域)
    windowed = np.lib.stride_tricks.as_strided(grid,
        shape=(current_size-2, current_size-2, 3, 3),
        strides=grid.strides * 2)
    water_counts[1:-1,1:-1] = np.sum(1 - windowed, axis=(2,3))
    
    # 处理四个角落
    water_counts[0,0] = np.sum(1 - grid[0:2,0:2])
    water_counts[0,-1] = np.sum(1 - grid[0:2,-2:])
    water_counts[-1,0] = np.sum(1 - grid[-2:,0:2])
    water_counts[-1,-1] = np.sum(1 - grid[-2:,-2:])
    
    # 处理上下边缘(非角落)
    water_counts[0,1:-1] = np.sum(1 - grid[0:2,1:-1], axis=0)
    water_counts[-1,1:-1] = np.sum(1 - grid[-2:,1:-1], axis=0)
    
    # 处理左右边缘(非角落)
    water_counts[1:-1,0] = np.sum(1 - grid[1:-1,0:2], axis=1)
    water_counts[1:-1,-1] = np.sum(1 - grid[1:-1,-2:], axis=1)
    
    return water_counts

4. 测试与验证

# 生成1024x1024的地图
final_map = upscale_and_process_borders(np.ones((4,4), dtype=bool), 1024)
print(f"陆地占比: {np.mean(final_map):.2%}")

性能提升核心点

  • 彻底消除Python循环:所有核心计算用NumPy向量化操作完成,避开解释器的性能瓶颈
  • 批量处理逻辑:一次性完成所有边界瓦片的邻域统计、概率计算和子瓦片转换,替代逐个check_tile的冗余操作
  • 高效网格放大:用np.repeat快速生成放大网格,比手动拆分瓦片的效率提升数十倍

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:25:06