numpy 转 torch , GPU 并行计算

2023-10-02 11:37:31 +08:00
 xddd9485

代码小白, 写代码的时候直接使用 numpy , 没考虑到之后要用 GPU

目前是打算用 Colab 跑这些代码

求各位大神帮帮忙, 怎么改动才能把这些需要多次调用的函数使用 GPU 计算 (在后面的代码中也会用到 PSO 之类的东西)



import numpy as np
import pandas as pd

import warnings
warnings.filterwarnings('ignore')


# @title 阴影确定

# ### 1]. 判断点是否在阴影内
# Displaying all the modified functions
def is_left(P0, P1, P2):
    """Determine if point P2 is to the left of the line segment from P0 to P1."""
    return (P1[0] - P0[0]) * (P2[1] - P0[1]) - (P2[0] - P0[0]) * (P1[1] - P0[1])

# 绕射法判断点是否在多边形内部
def winding_number_revised(P, polygon_corners):
    """Revised winding number function."""
    wn = 0
    num_vertices = len(polygon_corners)

    # Iterate through the edges of the polygon
    for i in range(num_vertices - 1):
        if polygon_corners[i][1] <= P[1] < polygon_corners[i+1][1]:  # Upward crossing
            if is_left(polygon_corners[i], polygon_corners[i+1], P) > 0:
                wn += 1
        elif polygon_corners[i+1][1] <= P[1] < polygon_corners[i][1]:  # Downward crossing
            if is_left(polygon_corners[i], polygon_corners[i+1], P) < 0:
                wn -= 1

    # Convert wn to binary (inside/outside) value
    return 1 if wn != 0 else 0



# ### 2]. 角点计算
# 角点排序
def sort_corners(unsorted_corners, center):
    """Sort corners in counter-clockwise order."""
    vectors = [np.array(corner) - np.array(center) for corner in unsorted_corners]
    angles = [np.arctan2(vector[1], vector[0]) for vector in vectors]
    sorted_corners = [corner for _, corner in sorted(zip(angles, unsorted_corners))]
    return sorted_corners

# 确保凸四边形的情况下计算角点
def debug_compute_corners_corrected(center, normal, K, L):
    """Compute corners ensuring they form a convex parallelogram."""
    v = np.array([0, 0, 1])  # Assuming z-axis as a reference vector
    if np.allclose(normal, v) or np.allclose(normal, -v):  # If normal is aligned with z-axis, take another reference
        v = np.array([1, 0, 0])

    dir1 = np.cross(normal, v)
    dir1 = dir1 / np.linalg.norm(dir1)
    dir2 = np.cross(normal, dir1)
    dir2 = dir2 / np.linalg.norm(dir2)

    half_K = K / 2
    half_L = L / 2
    corner1 = center + half_K * dir1 + half_L * dir2
    corner2 = center + half_K * dir1 - half_L * dir2
    corner3 = center - half_K * dir1 - half_L * dir2  # Swapped the ordering to ensure convex shape
    corner4 = center - half_K * dir1 + half_L * dir2  # Swapped the ordering to ensure convex shape

    return corner1, corner2, corner3, corner4

# 存储角点
def compute_matrix_corners_sorted_v4(data, K, L):
    """Computes the matrix corners with the corrected function and includes z-coordinates."""
    corners = data.apply(lambda row: debug_compute_corners_corrected([row["x(m)"], row["y(m)"], row["z(m)"]],
                                                                     [row["x_normal"], row["y_normal"], row["z_normal"]],
                                                                     K, L), axis=1)

    # Sort the corners
    corners = corners.apply(lambda x: sort_corners(x, [0, 0, 0]))

    data['Corner1_x'] = corners.apply(lambda x: x[0][0])
    data['Corner1_y'] = corners.apply(lambda x: x[0][1])
    data['Corner1_z'] = corners.apply(lambda x: x[0][2])
    data['Corner2_x'] = corners.apply(lambda x: x[1][0])
    data['Corner2_y'] = corners.apply(lambda x: x[1][1])
    data['Corner2_z'] = corners.apply(lambda x: x[1][2])
    data['Corner3_x'] = corners.apply(lambda x: x[2][0])
    data['Corner3_y'] = corners.apply(lambda x: x[2][1])
    data['Corner3_z'] = corners.apply(lambda x: x[2][2])
    data['Corner4_x'] = corners.apply(lambda x: x[3][0])
    data['Corner4_y'] = corners.apply(lambda x: x[3][1])
    data['Corner4_z'] = corners.apply(lambda x: x[3][2])

    return data



# ### 3]. 反射光线计算
# 每枚镜子反射光线计算
def compute_reflected_light_direction(V, B, data_with_plane_equation):
    """Compute the direction of the reflected light."""
    # 通过镜子座标检索 data_with_plane_equation 中对应的镜子法向量
    matching_row = data_with_plane_equation[(data_with_plane_equation["x(m)"] == B[0]) &
                                            (data_with_plane_equation["y(m)"] == B[1]) &
                                            (data_with_plane_equation["z(m)"] == B[2])]

    if matching_row.empty:
        return None

    # 提取镜子的法向量
    normal = np.array([matching_row["x_normal"].values[0],
                       matching_row["y_normal"].values[0],
                       matching_row["z_normal"].values[0]])

    # 计算反射光线的方向向量
    V_reflected = V - 2 * np.dot(V, normal) * normal

    return V_reflected


# ### 4]. 交点转化判断
# 计算平面方程
def compute_plane_equation(data):
    """Compute the equation of the plane for each mirror."""
    A_values, B_values, C_values, D_values = [], [], [], []
    for index, row in data.iterrows():
        P1 = np.array([row["Corner1_x"], row["Corner1_y"], row["Corner1_z"]])
        P2 = np.array([row["Corner2_x"], row["Corner2_y"], row["Corner2_z"]])
        P3 = np.array([row["Corner3_x"], row["Corner3_y"], row["Corner3_z"]])
        v1 = P2 - P1
        v2 = P3 - P1
        n = np.cross(v1, v2)
        D = -np.dot(n, P1)
        A_values.append(n[0])
        B_values.append(n[1])
        C_values.append(n[2])
        D_values.append(D)
    updated_data = data.copy()
    updated_data['A'] = A_values
    updated_data['B'] = B_values
    updated_data['C'] = C_values
    updated_data['D'] = D_values
    return updated_data

# 计算线面交点
def compute_intersection(P0, d, plane_equation):
    """Compute the intersection point of line and plane."""
    A, B, C, D = plane_equation
    n = np.array([A, B, C])
    P0 = np.array(P0)
    t = -(np.dot(n, P0) + D) / np.dot(n, d)
    intersection = P0 + t * d
    return intersection

# 计算反射光线
def reflective_light_function_v2(x, y, z, d, plane_equation_df):
    """Determine if light is reflected from a given point to the viewer."""
    for _, row in plane_equation_df.iterrows():
        A, B, C, D = row['A'], row['B'], row['C'], row['D']
        corners = [
            (row["Corner1_x"], row["Corner1_y"]),
            (row["Corner2_x"], row["Corner2_y"]),
            (row["Corner3_x"], row["Corner3_y"]),
            (row["Corner4_x"], row["Corner4_y"]),
            (row["Corner1_x"], row["Corner1_y"])
        ]
        P0 = [x, y, z]
        intersection_point = compute_intersection(P0, d, (A, B, C, D))
        if winding_number_revised(intersection_point[:2], corners):
            return 1
    return 0


# ### 5]. 功能函数
# Displaying the remaining modified functions
def find_points_in_hemisphere(B, df, R):
    """Find mirrors that are within a hemisphere facing point B."""
    x_B, y_B, z_B = B.flatten()  # Flattening to ensure it's a 1D array
    vec_OB = np.array([x_B, y_B, z_B])
    rows_list = []

    for index, row in df.iterrows():
        x, y, z = row['x(m)'], row['y(m)'], row['z(m)']
        vec_P = np.array([x - x_B, y - y_B, z - z_B])
        distance_to_B = np.linalg.norm(vec_P)
        dot_product = np.dot(vec_OB, vec_P)

        if distance_to_B <= R and dot_product < 0:
            new_row = {
                'x(m)': row['x(m)'],
                'y(m)': row['y(m)'],
                'z(m)': row['z(m)'],
                'x_normal': row['x_normal'],
                'y_normal': row['y_normal'],
                'z_normal': row['z_normal']
            }
            rows_list.append(new_row)

    df_inside_hemisphere = pd.DataFrame(rows_list)
    return df_inside_hemisphere

# 分块扫描并记录
def block_scanning(data_all, data, plane_equation_data, V, num_blocks, K, L):
    """Block scanning function with corrected corner computations."""
    blocks = np.zeros((num_blocks, num_blocks))

    matching_row = data_all[(data_all["x(m)"] == data[0]) &
                            (data_all["y(m)"] == data[1]) &
                            (data_all["z(m)"] == data[2])]

    if matching_row.empty:
        return None

    normal = np.array([matching_row["x_normal"].values[0], matching_row["y_normal"].values[0], matching_row["z_normal"].values[0]])
    center = np.array([matching_row["x(m)"].values[0], matching_row["y(m)"].values[0], matching_row["z(m)"].values[0]])

    # Compute corners using the corrected function
    corner1, corner2, corner3, corner4 = debug_compute_corners_corrected(center, normal, K, L)

    corners = [corner1, corner2, corner3, corner4]

    dir1 = np.array(corner2) - np.array(corner1)
    dir2 = np.array(corner4) - np.array(corner1)

    step1 = dir1 / num_blocks
    step2 = dir2 / num_blocks

    d = compute_reflected_light_direction(V, data, data_all)

    for i in range(num_blocks):
        for j in range(num_blocks):
            block_center = np.array(corner1) + (i + 0.5) * step1 + (j + 0.5) * step2
            x, y, z = block_center

            A, B, C, D = matching_row["A"].values[0], matching_row["B"].values[0], matching_row["C"].values[0], matching_row["D"].values[0]
            z = (-D - A*x - B*y) / C

            # The reflective light function is omitted for now, but can be added back.
            result = reflective_light_function_v2(x, y, z, d, plane_equation_data)
            blocks[i, j] = result

    ratio = np.sum(blocks) / np.size(blocks)
    return ratio
1159 次点击
所在节点    机器学习
3 条回复
Muniesa
2023-10-02 13:26:08 +08:00
先试试 cupy 吧,改成 torch 需要把 ndarry 换成 tensor ,数学运算要换成 torch 版本的,有的操作 torch 不支持可能还要转回 numpy 来算
lbingl
2023-10-02 13:40:39 +08:00
让 GPT 帮你转换
hsfzxjy
2023-10-02 14:05:35 +08:00
用 jax ?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/978555

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX