这是我的问题的简约视图(删除所有不必要的细节)。从本质上讲,它是一个“汇编代码”执行者:
while(self.pc < len(self.memory)):
instruction = [int(i) for i in str(self.memory[self.pc])]
#simulated "switch" statement.
def switch(Opcode):
op1 = getOperand(instruction[1], instruction[2])
op2 = getOperand(instruction[3], instruction[4])
def add():
if op1['mode'] = self.modes['gpr']:
self.gpr[op1['gpr']] = op1['opValue'] + op2['opValue']
else:
self.memory[op1['opAddress']] = op1['opValue'] + op2['opValue']
self.clock += self.clockSpeed['add']
def subtract():
if op1['mode'] = self.modes['gpr']:
self.gpr[op1['gpr']] = op1['opValue'] - op2['opValue']
else:
self.memory[op1['opAddress']] = op1['opValue'] - op2['opValue']
self.clock += self.clockSpeed['subtract']
def invalid():
raise ValueError('invalid Opcode in instruction: {}'.format(instruction)
return {
0: add,
1: subtract,
"invalid": invalid
}.get(Opcode, "invalid")()
switch(instruction[0])
self.pc += 1
当我使用timeit module
使用大约40个元素的简单数组(稍微复杂的方法,但不多)运行此程序时,它确实需要相当长的时间:
print 'timing execution of execute: ', timeit.timeit('vm.CPUexecuteProgram()', setup="from __main__ import OS; vm=OS(); vm.AbsoluteLoader('../assembly_code/assemble_code.exe')")
timing execution of execute: 0.673621892929
我相信这个定义在每次迭代时都会“重新制作”。是否会有更有效的方式遵循此处显示的相同“模式”?如果可能的话,我想避免使用if / elif / else,以使其更具可读性。
答案 0 :(得分:1)
此:
if op1['mode'] = self.modes['gpr']:
需要:
if op1['mode'] == self.modes['gpr']:
进行所有比较。双重等于“确实是等于对吗?”。单一的等于是“从右向左分配,然后向右回”。
答案 1 :(得分:1)
是的,您的代码会在每条指令上创建所有函数和整个字典。在您的实际代码中(假设有40个不同的操作码),这意味着每条指令执行至少42个对象实例化(每个操作码1个,switch
,dict)。您可以简单地将循环不变部分(创建add
,sub
,...;创建操作码 - >&gt;函数dict)拉出循环,生成op1
和op2
参数,并将循环减少到:
while self.pc < len(self.memory):
instruction = ...
op1 = ...
op2 = ...
implementations[instruction](op1, op2)
self.pc += 1
这应该在相当一部分时间内减少。可能有其他地方可以优化一点,但因为那不是你真正的代码而且它很邋(几个语法错误,有些部分看起来不对)我会避免猜测。
答案 2 :(得分:1)
重新排列:
def add(op1, op2):
if op1['mode'] = self.modes['gpr']:
self.gpr[op1['gpr']] = op1['opValue'] + op2['opValue']
else:
self.memory[op1['opAddress']] = op1['opValue'] + op2['opValue']
self.clock += self.clockSpeed['add']
def subtract(op1, op2):
if op1['mode'] = self.modes['gpr']:
self.gpr[op1['gpr']] = op1['opValue'] - op2['opValue']
else:
self.memory[op1['opAddress']] = op1['opValue'] - op2['opValue']
self.clock += self.clockSpeed['subtract']
def invalid(op1, op2):
raise ValueError('invalid Opcode in instruction: {}'.format(instruction)
switch = {0: add, 1: subtract}
while (self.pc < len(self.memory)):
instruction = [int(i) for i in str(self.memory[self.pc])]
Opcode = instruction[0]
op1 = getOperand(instruction[1], instruction[2])
op2 = getOperand(instruction[3], instruction[4])
switch.get(Opcode, invalid)(op1, op2)
self.pc += 1
这样每次都不会重新定义所有方法。
答案 3 :(得分:1)
import operator
class Something(object):
_operations = {
0: lambda self, instruction: self._execute("add", instruction),
1: lambda self, instruction: self._execute("subtract", instruction),
"invalid": lambda self, instruction: self_invalid(instruction)
}
_operators = {
"add": operator.add,
"substract": operator.sub
}
def _execute(self, operation, instruction):
op1 = getOperand(instruction[1], instruction[2])
op2 = getOperand(instruction[3], instruction[4])
operator = self._operators[operation]
val = operator(op1, op2)
if op1['mode'] == self.modes['gpr']:
self.gpr[op1['gpr']] = val
else:
self.memory[op1['opAddress']] = val
self.clock += self.clockSpeed[operation]
def _invalid(self, instruction):
raise ValueError(
'invalid Opcode in instruction: {}'.format(instruction)
)
def _switch(self, instruction):
return self._operations.get(instruction[0], self._invalid)(self, instruction)
def whatever(self):
while self.pc < len(self.memory):
instruction = [int(i) for i in str(self.memory[self.pc])]
self._switch(instruction)
self.pc += 1