Что-то вроде следующего:
struct Vec2
{
int x, y;
};
struct Bounds
{
int left, top, right, bottom;
};
int main()
{
Vec2 topLeft = {5, 5};
Vec2 bottomRight = { 10, 10 };
Bounds bounds;
//___Here is copy operation
//___Note they're not in contiguous order, harder for the compiler?
bounds.left = topLeft.x;
bounds.bottom = bottomRight.y;
bounds.top = topLeft.y;
bounds.right = bottomRight.x;
}
Эти четыре задания можно сделать так:
memcpy(&bounds, &topLeft, sizeof(Vec2));
memcpy(&bounds.right, &bottomRight, sizeof(Vec2));
Мне интересно две вещи:
Я получил следующие результаты разборки для четырех копий:
bounds.left = topLeft.x;
00007FF642291034 mov dword ptr [bounds],5
bounds.bottom = bottomRight.y;
00007FF64229103C mov dword ptr [rsp+2Ch],0Ah
bounds.top = topLeft.y;
00007FF642291044 mov dword ptr [rsp+24h],5
bounds.right = bottomRight.x;
00007FF64229104C mov dword ptr [rsp+28h],0Ah
И, как ни странно, два memcpys — это разные инструкции для первого и второго, я не понимаю этого:
memcpy(&bounds, &topLeft, sizeof(Vec2));
00007FF64229105E mov rbx,qword ptr [topLeft] // This is only one instruction
memcpy(&bounds.right, &bottomRight, sizeof(Vec2));
00007FF642291063 mov rdi,qword ptr [bottomRight] // Compared to 6?
00007FF642291068 mov qword ptr [bounds],rbx
00007FF64229106D mov qword ptr [rsp+28h],rdi
00007FF642291072 jmp main+7Eh (07FF64229107Eh)
00007FF642291074 mov rdi,qword ptr [rsp+28h]
00007FF642291079 mov rbx,qword ptr [bounds]
Любой современный компилятор, поддерживающий потоки, должен учитывать зависимости команд и переупорядочение. С этой технологией она быстро обнаружит, что в наборе инструкций нет зависимостей, что означает, что они могут быть переупорядочены в линейном порядке памяти, а затем объединены.
Не то чтобы это, вероятно, имеет значение; кэш ЦП просто загрузит всю строку кеша при первом доступе и очистит всю строку кеша в более поздний момент. Эти операции занимают время, а не сами операции процессора.
Других решений пока нет …