В этом тестовом примере:
#include<numeric>
#include<iostream>
inline void f1(char * buf) {
(*buf) += 5;
}
inline void f2(char * buf) {
(*buf) += 7;
}
int main()
{
char ptr1,ptr2;
std::cin>>ptr1;
std::cin>>ptr2;
f1(&ptr1);
f2(&ptr2);
return ptr1+ptr2;
}
, который скомпилирован в следующие коды сборки с использованием -O3 и -march = cannonlake (in godbolt)
main:
sub rsp, 24
lea rsi, [rsp+14]
mov edi, OFFSET FLAT:_ZSt3cin
call std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char&)
lea rsi, [rsp+15]
mov edi, OFFSET FLAT:_ZSt3cin
call std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char&)
movzx eax, BYTE PTR [rsp+14] // f1 function entrance
movzx ecx, BYTE PTR [rsp+15] // f2 entrance interleaved
add eax, 5 // f1 compute
lea edx, [rcx+7] // f2 compute using another instruction (ilp)
movsx eax, al
movsx edx, dl
add eax, edx
add rsp, 24
ret
_GLOBAL__sub_I_main:
sub rsp, 8
mov edi, OFFSET FLAT:_ZStL8__ioinit
call std::ios_base::Init::Init() [complete object constructor]
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:_ZStL8__ioinit
mov edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
add rsp, 8
jmp __cxa_atexit
Это похоже на встраивание функцийпозволяет им преобразовываться в чередующуюся версию f1 + f2 и работать асинхронно на суперскалярном процессоре.Есть ли более прямой, формальный способ добиться этого?
Если я добавлю std :: async с отложенной политикой, он все равно будет чередовать инструкции функций с простыми вызовами f1 и f2, но на этот раз get()
метод будущегоделает "вызов", и вызов там не перемежается из-за инструкции "jump" после этого.
Попробовал std :: async следующим образом:
f1(&ptr1);
f2(&ptr2);
std::async(std::launch::deferred,f1,&ptr1).get();
std::async(std::launch::deferred,f2,&ptr2).get();
Может быть, не только get ()но также конструкторы и деструкторы «будущего» также вызывают эти вызовы и переходы.
Как я могу запустить группу функций (или даже лямбда-выражения?) или одну функцию с различными параметрами (как будто обрабатывает массив) не прибегая к «встроенному» iness-функциям (поскольку компилятор не гарантирует этого)?Возможен ли мелкозернистый параллелизм в одном и том же потоке?
Asynchronizator(0,100,[]()
{
runCode(parameter++);
});
, если это возможно с лямбдами, было бы даже лучше, но у них тоже есть конструкторы и деструкторы, являющиеся функторами.