Re: [讨论] 写三元判断式code review被打枪

楼主: erspicu (.)   2022-12-26 23:04:05
※ 引述《unixxxx (皓皓)》之铭言:
: 标题: Re: [讨论] 写三元判断式code review被打枪
: 时间: Sat Dec 17 03:51:38 2022
: 很多Javascript 高手都是用 switch 取代
"特定"情况下的确是好方式
举个例子 以前我在调校能时候有用过这种方式 这是c#的code部分节录
void Mem_w(ushort address, byte value)
{
if (address < 0x2000) NES_MEM[address & 0x7ff] = value;
else if (address < 0x4020) IO_write(address, value);
else if (address < 0x6000) MapperRouterW_ExpansionROM(address,value);
else if (address < 0x8000) MapperRouterW_RAM(address, value);
else MapperRouterW_PRG(address, value);
}
这个是一个非常频繁被呼叫的method 如果address 大于等于0x8000
其实前面就浪费好几次计算在判断式上
因此改成 功能上是相等的
static void Mem_w(ushort address, byte value)
{
switch (address & 0xf000)
{
case 0:
case 0x1000:
NES_MEM[address & 0x7ff] = value;
break;
case 0x2000:
case 0x3000:
case 0x4000:
IO_write(address, value);
break;
case 0x5000:
MapperObj.MapperW_ExpansionROM(address, value);
break;
case 0x6000:
case 0x7000:
MapperObj.MapperW_RAM(address, value);
break;
case 0x8000:
case 0x9000:
case 0xa000:
case 0xb000:
case 0xc000:
case 0xd000:
case 0xe000:
case 0xf000:
MapperObj.MapperW_PRG(address, value);
break;
}
}
但再简化快速下去还有大招
初始化执行一次就好
static void init_function()
{
mem_write_fun = new Action<ushort, byte>[0x10000];
for (int address = 0; address < 0x10000; address++)
{
if (address < 0x2000) mem_write_fun[address] =
new Action<ushort, byte>((addr, val) => { NES_MEM[addr & 0x7ff] = val; });
else if (address < 0x4020) mem_write_fun[address] =
new Action<ushort,byte>(IO_write);
else if (address < 0x6000) mem_write_fun[address] =
new Action<ushort, byte>(MapperObj.MapperW_ExpansionROM);
else if (address < 0x8000) mem_write_fun[address] =
new Action<ushort, byte>(MapperObj.MapperW_RAM);
else mem_write_fun[address] =
new Action<ushort, byte>(MapperObj.MapperW_PRG);
}
}
之后读取
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static void Mem_w(ushort address, byte value)
{
mem_write_fun[address](address, value);
}
实际上跟switch原理很相似 但直接把mapper的实作 哪个address对应啥动作
直接写到记忆址array去了
我是不知道你所谓的javascript高手用switch替代判断式是碰到啥议题
但特定议题用改用switch 甚至自己刻死路由效能是会快非常多
以前有笔记在这边...
https://dotblogs.com.tw/enet/2017/01/21/emu_optimization_1
作者: MoonCode (MoonCode)   2022-12-26 23:47:00
...快不快还是 benchmark 或看编译出来什么东西吧
作者: jason222333 (发呆)   2022-12-27 06:32:00
作者: DarkIllusion (′・ω・‵)   2022-12-27 06:48:00
好奇问 为什么这里switch-case会比多重if-else快?以及 为什么这里用function map比switch-case快?如果频繁判断address大于等于0x8000 那这判断放前面为什么不会是个好的解法?
作者: Jichang (C.C.Lemon)   2022-12-27 06:58:00
这不是大一计概就会教的 if else 是循序判断 switch 是jump map是hash 但是好的compiler可以直接最佳化if else
作者: DarkIllusion (′・ω・‵)   2022-12-27 07:01:00
抱歉 我比较没有计概常识看来原PO用的是没那么好的compiler :(
作者: leolarrel (真.粽子无双)   2022-12-27 13:44:00
单纯补充一下,这应该不适合在C. 刚用gcc 看组语内容,switch 仍然用比较且跳跃来实作
作者: MyNion (Nion Lee)   2022-12-27 15:54:00
你下面阵列开了六万多个再用for去跑,真的需要那么多个?因为你的case只有五种,要不要数字进来都/5,这样较省空间
作者: chuegou (chuegou)   2022-12-27 22:08:00
就算是C 还可以问你优化编译有没有开
作者: peter98 (新兵)   2022-12-27 22:35:00
这种其实没什么好讨论的 就算真的这样做有用 也只是单一case适用 另外 profiling的情况是有规定的 不是随便跑 上次不知道哪个人开debug mode做profiling 原本想说什么 后来想想还是算了打错 我是指开IDE去run程式做profiling
作者: wulouise (在线上!=在电脑前)   2022-12-28 12:27:00
开IDE跟profiling是之间没有关系,除非开debug build
作者: leolarrel (真.粽子无双)   2022-12-28 13:19:00
chuegou, 我用gcc -O0跟-O3测试.你也可以自己试试看
作者: ku399999   2022-12-30 09:37:00
好奇效能差很多最后是快多少 func功能还是比条件判断占更多执行时间才对

Links booklink

Contact Us: admin [ a t ] ucptt.com