Lua:代码优化矢量长度计算

如何解决Lua:代码优化矢量长度计算

| 我在游戏中有一个脚本,该脚本具有每秒被调用的功能。玩家对象与其他游戏对象之间的距离在那里每秒计算一次。问题在于,一秒钟内最多可能有800个函数调用(最多40个播放器* 2个主要对象(1个最多10个子对象))。我必须优化此功能以减少处理。这是我当前的功能:
local square = math.sqrt;

local getDistance = function(a,b)
    local x,y,z = a.x-b.x,a.y-b.y,a.z-b.z;
    return square(x*x+y*y+z*z);
end;

-- for example followed by: for i = 800,1 do getDistance(posA,posB); end
我发现,math.sqrt函数的本地化通过
local square = math.sqrt;
是关于速度和代码的重大优化
x*x+y*y+z*z
比以下代码更快:
x^2+y^2+z^2
我不知道x,y和z的本地化是否比使用类方法“ ..”更好,所以也许
square(a.x*b.x+a.y*b.y+a.z*b.z)
比代码
local x,a.z-b.z;
            square(x*x+y*y+z*z);
好 数学中是否有更好的方法来计算向量长度,或者Lua中是否有更多性能提示?     

解决方法

        您应该阅读Roberto Ierusalimschy的Lua Performance Tips(Roberto是Lua的首席设计师)。它涉及您所要求的一些小优化(例如,本地化库函数并用多倍等价物替换指数)。最重要的是,它传达了工程学中最重要且最容易被忽略的想法之一:有时最好的解决方案涉及更改问题。您不会通过减少计算所需的CPU周期数来解决3000万次计算泄漏。 在距离计算的特定情况下,您会发现最好使原始计算返回表示平方距离的中间和,并允许用例仅在需要时才调用毕达哥拉斯的最终步骤,通常不需要(例如,您不需要执行平方根即可比较两个平方长度中的哪个更长)。 不过,在进行任何有关优化的讨论之前,确实应该做到这一点:不要担心不是问题的问题。与其检查代码中是否存在任何可能的问题,不如直接解决最大的问题-如果在最明显的问题上性能超过了缺少的功能,错误和/或UX缺点,那么微效率低下几乎是不可能的。已经累积到超过单个瓶颈声明的程度。 或者,如被引文章的开头所述:   在Lua中,就像在任何其他编程语言中一样,我们应始终遵循两者   程序优化准则:      规则1:不要这样做。      规则2:不要这样做。 (仅适用于专家)     ,        老实说,我怀疑这些微优化真的对任何事情都没有帮助。 您应该专注于算法,例如通过修剪摆脱一些距离计算,停止计算值的平方根以进行比较(提示:如果
a^2
<
b^2
a
> 0和
b
> 0,则
a
<
b
)等     ,        您的“强力”方法无法很好地扩展。 我的意思是,系统中包含的每个新对象/播放器都会大大增加操作次数:
 +---------+--------------+
 | objects | calculations |
 +---------+--------------+ 
 |      40 |        1600  |
 |      45 |        2025  |
 |      50 |        2500  |
 |      55 |        3025  |
 |      60 |        3600  |
...       ...            ...
 |     100 |       10000  |
 +---------+--------------+
如果您继续比较“一切皆有”,您的算法将以一种古怪的方式开始占用越来越多的CPU周期。 优化代码的最佳选择不是进行数学运算“微调”,也不是使用局部变量代替引用。 真正提高您的算法效率的是消除不需要的计算。 如果您已经计算了Player2和Player1之间的距离,那么最明显的例子就是不计算Player1和Player2之间的距离。这种简单的优化应将您的时间减少一半。 另一个非常常见的实现方式是将空间划分为“区域”。当两个对象位于同一区域时,通常可以计算它们之间的间隔。当它们位于不同的区域时,可以使用近似值。划分空间的理想方式取决于您的环境。例如,将空间划分为网格,对于不同正方形的玩家,请使用您预先计算的正方形中心之间的距离)。 编程中有一个完整的分支处理该问题。称为空间分区。看一下: http://en.wikipedia.org/wiki/Space_partitioning     ,认真吗 运行800次这些计算所花费的时间不应超过0.001秒-即使在手机上使用Lua进行计算。 您是否进行了分析以查看它是否真的使您放慢了脚步?您是否用\“ return(0)\”替换了该功能,以验证性能是否提高(是的,该功能将丢失)。 您确定它每秒运行一次,而不是每毫秒运行一次吗? 自1987年以来,我还没有看到在1秒钟内运行800个简单事物的问题。     ,        如果要计算正数
a
的sqrt,则采取递归序列
x_0 = a
x_n+1 = 1/2 * (x_n + a / x_n)
x_n
n -> infinity
移至
sqrt(a)
。前几次迭代应该足够快。 顺便说一句!也许您会尝试使用以下公式计算标准输入向量的长度。
local getDistance = function(a,b)
    local x,y,z = a.x-b.x,a.y-b.y,a.z-b.z;
    return x+y+z;
end;
它更容易计算,并且在某些情况下(例如,如果需要距离来确定两个物体是否靠近),它可能就足够了。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-