【问题标题】:What can I do to optimize my MIPS code further?我可以做些什么来进一步优化我的 MIPS 代码?
【发布时间】:2021-11-12 06:40:28
【问题描述】:

我正在为我的作业优化我的代码。我需要将总能量输出减少至少 5%。我在下面包含了我的代码。到目前为止,我只能将能量输出减少 2%。这是通过调整我的 sub $t0,$t0, 32 并引入另一个初始化为 -32 的寄存器($t8)并将上面的代码替换为 add $t0,$t0,$t8 来实现的。这行代码在标签下小写点。

代码的目的是输入一个句子并计算特定字母的字符数,然后以数字和井号显示该字符数。

我已经盯着我的代码看了好几个小时,试图弄清楚我能做什么,但什么都没有。任何帮助将不胜感激。

谢谢

#NAme
#Comp Org
#Homework 2A

.data
string: .asciiz "\nEnter A String:"     #prompts the user to input a string
input: .space 1000
.text


li $v0,4            #printing the string
la $a0,string           #prompt for the string
syscall             #executing

li $v0,8 
la $a0,input            #prompting for the users input
li $a1,1000                 #loading 1000 into the register
syscall
move $s0,$a0                #moving the data into the new register

li $t0,0 #this register will be used for the count of c
li $t1,0 #this register will be used for the count of h
li $t2,0 #this register will be used for the count of a
li $t3,0 #this register will be used for the count of r
li $t4,0 #this register will be used for the count of e 
li $t5,0 #this register will be used for the count of o
li $t6,0 #this register will be used for the count of n
li $t7,0 #this register will be used for the count of g

li $t8,-32  #this will be used for the addition
loop: #loop for the string

lb $a0,0($s0) #load the first character into $a0
addi $s0,$s0,1 #used as an index and increments by 1
beq $a0,$zero,done #used as the else clause
sge $s5,$a0,'a' #checks for the lowercase range
sle $s6,$a0,'z' #checks for the lowercase range 
and $s5,$s5,$s6 #and condition used to check between the range of lowercase
beq $s5,1,lowercaseCount #branch to lowercase label

j calculate #jump to calculate label

lowercaseCount:
add $a0,$a0,$t8   #subtracts 32 from the value stored in $a0

calculate:

beq $a0,'C',cCount      #branching and checking for capital occurences for each one
beq $a0,'H',hCount
beq $a0,'A',aCount
beq $a0,'R',rCount
beq $a0,'E',eCount
beq $a0,'O',oCount
beq $a0,'G',gCount
beq $a0,'N',nCount

j exitCount

gCount:
add $t7,$t7,1 #incrementing gCount by 1
j exitCount

cCount:
add $t0,$t0,1 #Incrementing cCount by 1
j exitCount

hCount:
add $t1,$t1,1 #incrementing hCount by 1
j exitCount

aCount:
add $t2,$t2,1 #Incrementing aCount by 1
j exitCount

rCount:
add $t3,$t3,1 #incrementing rCount by 1
j exitCount

eCount:
add $t4,$t4,1 #Incrementing eCount by 1
j exitCount

oCount:
add $t5,$t5,1 #incrementing oCount by 1
j exitCount

nCount:
add $t6,$t6,1 #incrementing nCount by 1
exitCount:

j loop


done:

li $a0,'C' #checks for the uppercase letter and moves into the new register
move $a1,$t0 #and moves into the new register
jal printCount


li $a0,'H' #checks for the uppercase letter and moves into the new register
move $a1,$t1 #and moves into the new register
jal printCount

li $a0,'A' #checks for the uppercase letter and moves into the new register
move $a1,$t2 #and moves into the new register
jal printCount

li $a0,'R' #checks for the uppercase letter and moves into the new register
move $a1,$t3 #and moves into the new register
jal printCount

#li $a0,'G' #checks for the uppercase letter and moves into the new register
#move $a1,$t7 #and moves into the new register
#jal printCount


li $a0,'E' #checks for the uppercase letter and moves into the new register
move $a1,$t4 #and moves into the new register
jal printCount

li $a0,'O' #checks for the uppercase letter and moves into the new register
move $a1,$t5 #and moves into the new register
jal printCount

li $a0,'N' #checks for the uppercase letter and moves into the new register
move $a1,$t6 #and moves into the new register
jal printCount

li $a0,'G' #checks for the uppercase letter and moves into the new register
move $a1,$t7 #and moves into the new register
jal printCount


move $v0,$a0        #moves the register
li $v0,11       #prints the character
syscall



li $a0, 'C'     #loads C into register
move $a1,$t0        #moves value of $t0 into a1
syscall
jal printhash       #jump and link to printhash

li $a0, 'H'     #loads H into register
move $a1,$t1        #moves value of $t1 into $a1
syscall 
jal printhash       #jump n link to printhash

li $a0, 'A'     #loads A into register
move $a1,$t2        #move the register from $t2 into $a1
syscall
jal printhash

li $a0, 'R'     #loads R into register
move $a1,$t3        #move the register from $t3 into $a1
syscall
jal printhash       #jumps to printhash
    
li $a0,'E'      #loads E into register
move $a1,$t4        #move the register from $t4 into $a1
syscall
jal printhash       #jumps to printhash

li $a0, 'O'     #loads O into register
move $a1,$t5        #move the register from $t5 into $a1
syscall
jal printhash       #jumps to print hash

li $a0,'N'      #loads N into register
move $a1,$t6        #move the register from $t6 into $a1
syscall
jal printhash       #jumps to printhash

li $a0, 'G'     #loads G into register
move $a1,$t7        #move the register from $t7 into $a1
syscall
jal printhash       #jumps to printhash

li $v0,10       #syscall to terminate the program once this loop has been executed
syscall

printCount:

move $v0,$a0 #prints the character
li $v0,11
syscall

li $a0,':' #prints the character
li $v0,11
syscall
move $a0,$a1 #prints the current count

li $v0,1 
syscall

li $a0,'\n' #prints the newline 
li $v0,11
syscall

jr $ra

printhash:

#move $v0,$a0 #prints the character
#li $v0,11
#syscall

li $a0,':' #prints the character
li $v0,11
syscall
move $a0,$a1 #prints the current count

li $s7,0        #indexing for the loop

hash:
bge $s7,$a1,exithash        #loop condition branch to exit loop if equal
li $a0,'#'          #loads # into the register
syscall
addi $s7,$s7,1          #adding 1 to the value in the register $s7

j hash              #jumping back to the start of the loop

exithash:           #label  of exit loop

li $a0,'\n'         #loading new line
li $v0,11           #printing the new line
syscall             #executing syscal

jr $ra              #jumping back to register $t1



【问题讨论】:

  • 使用数组可能会更便宜。寄存器很棒,让beq 分支链分派到正确的add 指令可能比加载和存储成本更高。 (特别是如果您使用几个单独的数组展开以隐藏存储/重新加载延迟。)
  • 您正在调整哪种 MIPS 微架构?它是一个真正的 MIPS,它的延迟分支是你的汇编程序为你隐藏的(例如,在背靠背的 beq 指令之间放置一个 nop)? (所以如果你用.set noreorder 组装你的代码会被破坏?)或者它是一个没有分支延迟槽的假MIPS?您正在优化能量,而不是原始速度?这个 CPU 的成本模型是多少?无论是在能量方面,还是在存储/重新加载、加载使用延迟和管道宽度等内容的延迟周期方面。乱序执行,还是我们需要手动做软件流水线?
  • 我假设它是假的 MIPS。我们在使用 MIPS 32 的 MARS 4.5 中编写代码。家庭作业是减少指令计数产生的总能量。
  • 我查看了 MARS 4.5 并没有看到任何直接测量能量或功率的工具或其他菜单项。那么您使用的是什么成本模型?执行的每条指令是否消耗相同的能量?那将是不切实际的,如果这就是您的意思,您还不如说“最小化动态指令数”。在真正的 CPU 中,浮点指令通常比整数指令消耗更多功率,从而使 CPU 运行更热。
  • 最后一次,您使用的成本模型是什么? ALU 指令相对于分支或内存要消耗多少能量?我确信有一些优化不依赖于权衡的细节,但在我花时间研究它之前,我想知道相对成本以了解它会有多大的胜利例如,转换为内存中的索引计数器。

标签: assembly optimization mips cpu-architecture mips32


【解决方案1】:

你有:

     beq .... lowercaseCount
     j calculate
lowercaseCount:
    ...
calculate:

这个beq 围绕单个跳转指令进行分支。那可以优化去掉跳转,如下:分支代替计算,在相反的条件下!

    bne calculate
    ...
calculate:

此外,您有 j exitCountj loop

这是一个无条件分支到另一个无条件分支,可以优化。将所有 j exit 替换为 j loop 以跳过不必要的跳跃。

【讨论】:

  • 非常感谢您的指导和解释。我们仍在学习如何正确有效地使用 MIPS 进行编码,所以这非常有帮助!
  • 所以 beq to bne 工作,但是当我将所有退出计数切换到 j 循环时,代码将无法正常工作。我删除了每个 j exitCount,并用 j loop 替换了每个出现的地方,并将 exitCount 更改为 exitloop。我不明白我做错了什么
  • 好的,但是您得到了可以优化无条件分支到无条件分支的概念。建议回到未优化的原始状态,一次只进行一个更改,比如从更改第一个 j exitCount 开始,然后尝试一下。这些是逻辑上等价的转换,所以肯定会起作用,只需要在这样做时找到一个错字。测试之间不要改变太多,以便更容易发现错误。
  • 标签也不要乱弄,修改j指令目标,作为本次优化的应用。
  • 我明白了!非常感谢您的帮助!
猜你喜欢
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多