zoukankan      html  css  js  c++  java
  • 用 CPU 计算 100 万 个 点 的 三维坐标 旋转

    一次 三维旋转 由  3 次 二维旋转 组成 ,  分别 是 围绕 x 轴 旋转,  围绕 y 轴 旋转,  围绕 z 轴 旋转  。   记 围绕 x 轴 、y 轴 、z 轴 旋转 的 角度 为  θx , θy , θz  。

    二维平面 上 的 坐标旋转 公式 

    x ′ = x cos A - y sin A

    y ′ = y cos A + x sin A

    x ′, y ′  为 旋转 后 的 坐标  。

    根据 二维平面 上 的 坐标旋转 公式  可以 推导 出 三维坐标旋转公式,   记 旋转 后的 坐标 为   x ′, y ′, z ′  。

    先 围绕 z 轴 旋转,  θz 的 基准 :   x 轴 正方向 朝右,  y 轴 正方向 朝上,  逆时针旋转 则 θz 为 正,  顺时针旋转 则 θz 为 负 。

    x ′  =  x cos θz  -  y sin θz 

    y ′  =  y cos θz + x sin θz

    z ′  =  z                                (保持不变)

    再 围绕 y 轴 旋转,  θy 的 基准 :   x 轴 正方向 朝右,  z 轴 正方向 朝上,  逆时针旋转 则 θy 为 正,  顺时针旋转 则 θy 为 负 。

    x ′ =  ( x cos θz  -  y sin θz  ) cos θy - z sin θy

    y ′  =  y cos θz + x sin θz             (保持不变)

    z ′ =  z cos θy +  ( x cos θz  -  y sin θz ) sin θy

    再 围绕 x 轴 旋转,  θx 的 基准 :   y 轴 正方向 朝右,  z 轴 正方向 朝上,  逆时针旋转 则 θx 为 正,  顺时针旋转 则 θx 为 负 。

    x ′ =  ( x cos θz  -  y sin θz  ) cos θy - z sin θy         (保持不变)

    y ′ =  ( y cos θz + x sin θz ) cos θx  -  [  z cos θy +  ( x cos θz  -  y sin θz ) sin θy  ]  sin θx

    z ′ =  [  z cos θy +  ( x cos θz  -  y sin θz ) sin θy  ]  cos θx  +  ( y cos θz + x sin θz )  sin θx

    这个 公式 有点繁琐  。   实际在 程序里 计算时,   直接把 上次 二维旋转 后 的 x, y, z 代入 下次 旋转 计算,  这样 每次计算 都是 二维旋转,  使用的是 二维旋转 的 公式  。

    项目地址 :     https://github.com/kelin-xycs/PointsRotate

    测试结果 :

    测试 的 CPU 是 2 核 4 线程,  两个 核 一个 主频 1.7 GHz, 一个 主频 2.4 GHz  。 总的来看,   2 个 线程 就可以达到 最快 了  。    其实 快慢 还跟 线程 是否 被 操作系统 安排 到 主频 高 的 那个 核 (2.4 GHz)  有关  。

    图中 红线处 可以看到,   执行速度 可以达到 每秒 无穷 次 ,   其实 不是真的 无穷,  而是  执行 的 时间(毫秒数) 太小, 小于 DateTime 的 刻度,   故 按 0 毫秒 算  。   时间 为 0,  除以 0 得 无穷  。

    总的来说,    1 秒 1000 次 是 没问题,     每次 旋转 100 万 个 点  。    如果 是  3D 游戏 的 话,   每一帧  旋转 100 万 个 点,  那么 可以 支持 每秒  1000 帧  。  当然 这只算了 旋转点, 没有包括 其它 工作量  。

    其实 这个测试 就是 一秒 计算多少次 乘法 和 加法,    并不稀奇  。    但 如果 带了  “能不能用 CPU 多核计算 代替  FPGA / DSP / GPU”  这个问题来看,   这个 测试结果 就有 意义 了  。

    第一次 测试 时,    程序 会 在 lock 块 里 创建 测试数据,  就是 100 万 个点 的 坐标,  是 一个 长度 为 100 万 的 数组  。  lock 块 可以将 这些数据 同步到 各个 核 的 Cache  。  而 测试完成 后,   测试数据 在 各个线程 所在的 核 的  Cache ,   并没有再 同步,   这是 因为 计算完后,   这些 数据 是要 顺序输出,  还是 接着 在 各个核 上 继续计算,    这个是不一定的,   由 实际 的 应用 决定  。

    自己编译 这个 程序 的 话,   注意用  Release 模式,    这个测试 的 Release 版本 比 Debug 版本 快 约 10 倍  。

  • 相关阅读:
    《软件工程》-第三章随笔
    《软件工程》-第二章随笔
    《软件工程》-第一章随笔
    软件工程——理论、方法与实践③
    软件工程——理论、方法与实践②
    软件工程——理论、方法与实践①
    爬虫之SCRAPY
    爬虫之 App 爬取
    flask bootstrap
    爬虫之协程,selenium
  • 原文地址:https://www.cnblogs.com/KSongKing/p/15751119.html
Copyright © 2011-2022 走看看