Russian Qt Forum

Программирование => С/C++ => Тема начата: G-virus от Ноябрь 19, 2012, 21:46



Название: Ассемблерная вставка AT&T, быстродействие.
Отправлено: G-virus от Ноябрь 19, 2012, 21:46
Здравствуйте. Решил вот тут оптимизировать умножение матриц 4х4 с помощью ассемблерных вставок. Эффективность их решил проверить на квадратном корне. Для тестинга использую вот такой код

Код
C++ (Qt)
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
 
float __fastcall inline asm_sqrt(const float &x)
{
  float tmp;
  asm volatile ("fsqrt;" : "=st"(tmp) : "0"(x));
  return tmp;  
}
 
int main(void)
{
  long start, end;
 
 
  start = clock();
     for(int i = 0; i < 1000; ++i)
    for(int x = 0.0; x < 1000000.0; x+=1.0)
   asm_sqrt(x);
  end = clock();
  printf("Assembler function: %ld\n", (end - start)/CLOCKS_PER_SEC);
 
  start = clock();
     for(int i = 0; i < 1000; ++i)
    for(int x = 0.0; x < 1000000.0; x+=1.0)
   sqrt(x);
  end = clock();
  printf("C function: %ld\n", (end - start)/CLOCKS_PER_SEC);
 
  system("pause");
  return 0;
}
 

В результате получается, что ассемблерная функция в таком цикле работает примерно 30 секунд на моей не самой мощной машине с кучей запущенных фоновых приложений. А Си-шная функция работает около 17 секунд. Вопрос: как вы считаете, почему это так? По идее, на ассемблере должно работать быстрее


Название: Re: Ассемблерная вставка AT&T, быстродействие.
Отправлено: Bepec от Ноябрь 19, 2012, 22:01
По великому секрету, расскажу одну историю. (Кто не хочет читать, краткое содержание в конце)

Был один НИИ. Было там 3 (три) специалиста, двое умных, а один молодой.

Понадобились жуткие вычисления. Стали думать - на чём писать.

Умные: "Ассемблер. Быстрее его нету".
Молодой: "С++. Быстрее и проще".

Начали писать 2 программы. Умные на ассемблере пишут, друг с другом переговариваются, 2 недели писали.
А молодой взял да и написал за 15 минут, а оставшееся время фуй пинал.

Начали сравнивать - Ассемблерная прога быстрее в 5 раз. Возрадовались Умные, долго кричали С++ маст дай и прочее.
А потом молодой репу почесал, сел, Страуструпа открыл и переписал 2 цикла. И стала программа на С++ быстрее.

Доолго кричали и ругались Умные, дооолго орали и утверждали что Ассемблер рулит. Вот только одного не учли.
На сегодняшний день компиляторы учитывают архитектуру процессоров, используют алгоритмы оптимизации, выверенные годами.

Конечно, если написать на ассемблере самому, возможно и получится быстрее, но... Но в 80% случаев компилятор выдаст лучший вариант за 15 минут :)

PS краткое содержание - Ассемблер хорошо, но текущее развитие технологий даёт понять, что компилятор оптимизирует быстрее и лучше человека, по сравнению время/качество.

PPS история реальная.

PPPS по специфике работы так же знаю, что ассемблерные вставки используются сейчас только под микроконтроллеры и армы. Но только с учётом всех особенностей каждого МК.


Название: Re: Ассемблерная вставка AT&T, быстродействие.
Отправлено: G-virus от Ноябрь 19, 2012, 22:17
Забавная история :)

PS краткое содержание - Ассемблер хорошо, но текущее развитие технологий даёт понять, что компилятор оптимизирует быстрее и лучше человека, по сравнению время/качество.

Вы советуете и перемножение матриц писать просто на С++, не влезая в дебри ассемблерных вставок? Или стоило бы почитать чего-нибудь и все таки попробовать написать обджект файл на ассемблере?


Название: Re: Ассемблерная вставка AT&T, быстродействие.
Отправлено: V1KT0P от Ноябрь 19, 2012, 22:27
В результате получается, что ассемблерная функция в таком цикле работает примерно 30 секунд на моей не самой мощной машине с кучей запущенных фоновых приложений. А Си-шная функция работает около 17 секунд. Вопрос: как вы считаете, почему это так? По идее, на ассемблере должно работать быстрее
Для понимания для начала надо сравнить ассемблерный код который сгенерил компилятор для обоих случаев. Не факт что вклинивание асм вставки не повлекло ненужных накладных расходов.


Название: Re: Ассемблерная вставка AT&T, быстродействие.
Отправлено: Bepec от Ноябрь 19, 2012, 22:28
Я бы советовал вам попробовать самому. А результаты потом запостить сюда.

PS мой "Гуру" в программировании привёл простой пример - старая(2000) года программа с ассемлерными вставками работала примерно раз в 15 медленнее простой реализации на С++. Потому что там использовалась ассемблерная вставка, которая на современных компах (Intel i7) только тормозит.

PPS тут люди, к примеру Igors, с матрицами работает. Надо б у него ещё совета спросить :)


Название: Re: Ассемблерная вставка AT&T, быстродействие.
Отправлено: G-virus от Ноябрь 19, 2012, 22:51
Я бы советовал вам попробовать самому. А результаты потом запостить сюда.

Да, я так и сделаю :) как раз, попробую не вставками а обджект файлом


Название: Re: Ассемблерная вставка AT&T, быстродействие.
Отправлено: porup от Ноябрь 20, 2012, 09:12
Скорее всего на вашем компьютере в данном тесте функция sqrt() не вызывается, поэтому второй цикл работает быстрее, а время в нем тратится на преобразования double в int
Код:
for(int x = 0.0; x < 100000.0; x+=1.0)
и прочую хер... при подготовке вызова sqrt().


Название: Re: Ассемблерная вставка AT&T, быстродействие.
Отправлено: Igors от Ноябрь 20, 2012, 11:32
Решил вот тут оптимизировать умножение матриц 4х4 с помощью ассемблерных вставок. Эффективность их решил проверить на квадратном корне.
Такая проверка неправомерна т.к. задачи совершенно разные. Умножение матриц не требует вставок и хорошо оптимизируется любым современным компилятором. Квадратный корень др дело, даже при первом взгляде в гуглу можно найти множество попыток. Общее мнение довольно однозначно - оптимизация математических вызовов (math.h) трудоемка и проблематична.

Интерес к таким вставкам пропадает очень быстро при первом же столкновении с разными ассемблерами на разных платформах. Напр Mac OS не всегда бегал на Intel. Лучше вспомнить что язык С был изобретен как замена ассемблера. Если аккуратно его использовать (а не ляпать классами абы-как) это даст лучшие результаты чем использование вставок.