#assembly #optimization #mips #cpu-architecture #mips32
Вопрос:
Я пытаюсь оптимизировать свой код для домашней работы. Мне нужно снизить общую выработку энергии минимум на 5 процентов. Я включил свой код ниже. До сих пор мне удавалось снизить выработку энергии только на 2 процента. Это было достигнуто путем настройки моего суб $t0,$t0, 32 и введения другого регистра($t8), инициализированного до -32, и замены вышеуказанного кода на add $t0,$t0,$t8.Эта строка кода находится под меткой LowerCasePoint.
Цель кода состоит в том, чтобы ввести предложение и указать количество символов для определенных букв, а затем отобразить это количество численно и со знаками фунта.
Я часами смотрел на свой код, пытаясь понять, что я могу сделать, и ничего не выскакивало у меня из головы. Любая помощь будет признательна.
Спасибо
#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
Комментарии:
1. Вероятно, было бы дешевле использовать массив. Регистры-это здорово, иметь такую цепочку
beq
филиалов для отправки по нужнойadd
инструкции, скорее всего, дороже, чем загрузка и хранение. (Особенно если вы разворачиваетесь с парой отдельных массивов, чтобы скрыть задержку хранения/перезагрузки.)2. Для какой микроархитектуры MIPS вы настраиваетесь? Является ли это реальным MIPS с отложенными ветвями, которые ваш ассемблер скрывает для вас (например, вводит
nop
beq
инструкции между строками)? (Значит, ваш код будет нарушен, если вы соберетесь вместе.set noreorder
?) Или это поддельный MIPS без слотов для задержки ветвей? Вы оптимизируетесь для энергии, а не для скорости? Какова модель затрат для этого процессора? Как с точки зрения энергии, так и с точки зрения циклов задержки для таких вещей, как хранение/перезагрузка, задержка использования нагрузки и ширина трубопровода. Вышедший из строя исполнитель, или нам нужно вручную выполнить конвейерную обработку программного обеспечения?3. Я предполагаю, что это поддельные MIPS. Мы пишем код в MARS 4.5, который использует MIPS 32. Домашнее задание состоит в том, чтобы уменьшить общее количество энергии, вырабатываемой при подсчете инструкций.
4. Я заглянул в MARS 4.5 и не увидел никаких инструментов или других пунктов меню для непосредственного измерения энергии или мощности. Итак, какую модель затрат вы используете? Стоит ли каждая выполняемая инструкция одинаковой энергии? Это было бы нереалистично, и вы могли бы просто сказать «минимизировать количество динамических команд», если это все, что вы имеете в виду. В реальных процессорах инструкции с плавающей запятой обычно потребляют больше энергии, чем целочисленные, что делает работу процессора более горячей.
5. В последний раз спрашиваю, какую модель затрат вы используете? Сколько энергии стоит инструкция ALU по отношению к ветви или памяти? Я уверен, что есть некоторые оптимизации, которые не зависят от деталей компромисса, но прежде чем я потрачу время на их изучение, я хочу знать относительные затраты, чтобы иметь представление о том, насколько выгодным было бы, например, преобразование в счетчики индексации в памяти.
Ответ №1:
У тебя есть:
beq .... lowercaseCount j calculate lowercaseCount: ... calculate:
Это beq
разветвляется вокруг одной инструкции по прыжку. Это может быть оптимизировано для удаления скачка следующим образом: вместо вычисления ветви, при обратном условии!
bne calculate ... calculate:
Далее, у вас есть j exitCount
, и вот оно j loop
.
Это безусловная ветвь к другой безусловной ветви, которую можно оптимизировать. Замените все j exit
на j loop
, чтобы пропустить этот ненужный прыжок.
Комментарии:
1. Большое вам спасибо за руководство и разъяснения. Мы все еще учимся правильно и эффективно кодировать с помощью MIPS, так что это очень полезно!
2. Таким образом, beq для bne работал, но когда я переключил все количество выходов на циклы j, код не работал должным образом. Я удалил все j- количество выходов и заменил каждое вхождение на j-цикл , а также изменил количество выходов на exitloop . Я не понимаю, что я сделал не так
3. Хорошо, но вы понимаете концепцию того, что безусловная ветвь к нетрадиционной ветви может быть оптимизирована. Предложите вернуться к исходному неоптимизированному варианту и вносить только одно изменение за раз, скажем, начиная с изменения только первого
j exitCount
, и попробуйте это сделать. Это преобразования, которые логически эквивалентны, поэтому, безусловно, будут работать, просто нужно найти опечатку при этом. Не слишком сильно меняйтесь между тестами, чтобы было легче находить ошибки.4. Также не связывайтесь с метками, просто измените цель
j
инструкции, как это применимо к этой оптимизации.5. Я понял! Большое вам спасибо за вашу помощь!