Когда sizeof (myPOD) слишком велик для передачи по значению на x64? - PullRequest
6 голосов
/ 22 февраля 2012

Я не ожидаю никакой разницы, когда речь идет о структурах размером до 8 байт, но как насчет больших типов POD? Становится ли передача по значению дороже в тот момент, когда размер типа превышает размер машинного слова, или есть что-то еще (например, размер строки кэша), которое может повлиять на производительность?

В основном я интересуюсь x64, но не стесняйтесь включать некоторые цифры и для x86.

Разъяснения:

  • Я, вероятно, думаю слишком узко, потому что я не знаю всего, что играет в этом роль (регистры, соглашения о вызовах, оптимизации компилятора). В основном меня интересует компилятор Microsoft C ++, и он использует только __fastcall.
  • Мне интересно, есть ли какие-либо общие рекомендации, когда речь идет о передаче параметров, зная архитектуру, размер шрифта, размер кэша и т. Д. Что-то вроде: «Предпочитают передавать тип по значению, когда он меньше N байтов. " где N - это то, что может быть получено из вещей, которые мы знаем.

Ответы [ 2 ]

7 голосов
/ 22 февраля 2012

Вы путаете две отдельные проблемы.Вы можете передать любой объект по значению (при условии, что он копируется).

Будет ли он передан в регистр или от стека зависит отреализацию и, в частности, используемое соглашение о вызовах.

При некоторых соглашениях о вызовах параметры размером более 8 байт (размер регистра общего назначения) будут передаваться в стеке.В соответствии с другими соглашениями о вызовах их можно просто разделить на несколько регистров.

В некоторых случаях возможно, что объекты никогда не передаются в регистрах независимо от их размера.

Аналогично, значения SIMD (SSE / AVX) могут передаваться в регистрах в некоторых соглашениях о вызовах, но всегда будут помещаться в стек в других.И то же самое может быть справедливо для скалярных значений с плавающей запятой.

Но то, что вы спрашиваете, не может быть осмысленно получено.Скорость копирования объекта зависит от размера объекта, да.Если объект относится к типу POD и вписывается в регистр, то его можно скопировать с помощью простой инструкции mov.Независимо от того, будет ли компилятор делать , что зависит от компилятора.

И, очевидно, чем больше объект, тем больше кэш-памяти он занимает, а значит, вы получите большекэш пропускает.

Но это все настолько расплывчато, что почти бесполезно.Мы не знаем, как выглядит ваш объект, и мы не знаем, что ваш код делает с ним .Если вы имеете в виду определенный тип, то напишите эталонный тест, чтобы увидеть, как он обрабатывается компилятором.

В ответ на ваши изменения

Мне интересно, есть ли какие-либо общие рекомендации, когда речь идет о передаче параметров, зная архитектуру, размер шрифта, размер кэша и т. Д. Что-то вроде: «Предпочитают передавать тип по значению, когда он меньше Nбайт.

Во-первых, доверьтесь компилятору. Во многих ситуациях он будет активно оптимизировать удаление копий, поэтому даже если вы do передаете большой объект по значению, вряд ли это будетизмеримая проблема.

Во-вторых, вы смотрите на микрооптимизацию, которая вряд ли будет иметь заметное значение в любом случае. Для небольших объектов передача по значению избегает косвенного указателя, так что, вероятно, немного быстрее.это становится перегружено стоимостью копирования (при условии, что объект скопирован , см. выше). Для очень больших объектов(ради аргумента, скажем, 500 байт или выше, таких больших, что объекты обычно не достигают его), вам определенно следует пройти по ссылке.

Но для объектов 8, 16, 24, 40 байт?Кто знает?Какая разница?Маловероятно, что в реальном коде будет ощутимая разница.

Что приводит меня к двум эмпирическим правилам:

  1. делает то, что кажется естественным: если передача с помощью копирования делает ваш код проще иличище, делайте это.
  2. если производительность имеет значение, то (1) убедитесь, что то, на что вы смотрите, действительно любое заметно влияет на вашу производительность вообще.Измерь это.Если это влияет на производительность, то это можно измерить.Если его невозможно измерить, то разница в производительности по определению не может быть заметной.

Итак, вкратце:

  • для типов примитивов, проходите мимоЗначение.
  • для очень крупных типов, передайте по ссылке.
  • для всего остального, перестаньте беспокоиться и потратьте время на что-то продуктивное.
0 голосов
/ 22 февраля 2012

Вас должны беспокоить две вещи - копирование данных и использование стека.

Копирование данных требует времени.Чем больше структура, тем больше времени потребуется для ее копирования.Будет ли это производительность или нет, зависит от того, как часто вы это делаете, и каковы требования к производительности вашего кода.

Стек большой, но не бесконечный.Передача больших структур по значению, особенно в сочетании с рекурсией, может легко привести к ее переполнению.

В x86_64 (с использованием соглашений WIN64 или Linux) существует меньшая точка передачи данных в регистрах.Если параметры имеют размер до 8 байтов каждый, первые 6 передаются в регистрах, что быстрее.В x86 большинство соглашений этого не делает (ядро Linux использует 3 регистра для параметров).
Использование reigsters несколько быстрее.Но разница между передачей 8 байтов с использованием стека или регистра невелика по сравнению с разницей между копированием 8 байтов и 1000 байтов.

...