ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 марта
705542 Топик полностью
Ксения (13.10.2016 21:32 - 21:39, просмотров: 218) ответил misyachniy на Я проголосовал бы против ассемблера.
Чего там тасовать? Задача проще выведенного яйца. Вот цикл: cycle: vmovupd ymm1, [esi] ;ymm1=[esi] add esi, 32d vfmadd231pd ymm0, ymm1, [ebx] ;ymm0+=ymm1*[ebx] add ebx, 32d loop cycle где: vmovupd загружает из первого массива по адресу [esi] 4 последовательно стоящих числа типа float64 (double) в длинный регистр ymm1. vfmadd231pd умножает числа, ранее загруженные в регистр ymm1, на 4 последовательно стоящих числа из второго массива по адресу [ebх] и тут же прибавляет это произведение к регистру ymm0, который перед циклом был занулен. add инкрементируют адреса в обоих массивах. Т.е. это по сути операция: ymm0 += (ptr1++) * (ptr2++); С тем лишь исключением, что в операции участвуют сразу 4 последовательных числа из каждого массива, и, соответственно этому, шаг здесь тоже в 4 раза шире. Написать это короче попросту невозможно! А ветвление тут и предсказывать нечего, т.к. оно идет не вперед, а назад. Т.е. в этом цикле компилятору не приходится на каждом обороте цикла загружать из памяти новый код, т.к. на всем его протяжении работает старый. P.S. Конечно, код самой функции этим циклом не исчерпывается, поскольку приходится дополнительно считать остаток, когда длина массивов не кратна четырем double. А так же в самом конце суммировать между собой все 4 числа, накопленные в регистре ymm0. Но эти операции на общую продолжительность работы функции практически не влияют, т.к. выполняются всего 1 раз. Проблему вызывает совершенно другое явление - то, что операционная система переключает задачи/потоки (это она время процессора так между ними разделяет) в самом непредсказуемом месте. А это приводит к тому, что невидимо происходит временное сохранение регистров ymm в память при переходе к очередному потоку, а затем восстановление значения этих регистров из памяти, когда данная задача/поток снова активируются. Из-за этого эффекта расчет на громоздкой Windows 10 идет несколько дольше, чем на легкой Windows XP. И это несмотря на то, что я вычисляю продолжительность выполнения не по астрономическому времени, а по времени работы данного процесса (функцией GetThreadTimes() из WINAPI). И к тому же устанавливаю своему процессу максимальный для приложений приоритет (THREAD_PRIORITY_TIME_CRITICAL). Но, несмотря на это, непрерывную работу моего потока операционка временами прерывает, поскольку у ее системы приоритет все равно выше.