Google Recruiter
-
- Уже с Приветом
- Posts: 17281
- Joined: 07 Sep 2011 10:05
- Location: Seattle, WA
Re: Google Recruiter
Мой ответ на этот вопрос будет - "зависит от процессора, OS, мэмори пейджинга, реализации конкретной JVM и т.п.". Вполне возможно, что на каком-то другом процессоре или ОС или на другой реализации Джава (например, Далвик для Андроида или конкретно имлементации J2ME для какой-нибудь Нокии) - разницы по скорости не будет. Так что Джава код я никогда не буду оптимизировать по критерию - sequential или random access. Если производительность очень критична, значит спущусь на JNI уровень и буду писать под конкретную платформу/процессор.
Оптимизацию под Джава, как правило, нужно проводить только с точки зрения алгоритмов (тут я с Адда абсолютно согласен), но никак не с точки зрения процессорной оптимизации (т.к. то, что возможно убыстрит для одной платформы, может ухудшить производительность для другой платформы).
Оптимизацию под Джава, как правило, нужно проводить только с точки зрения алгоритмов (тут я с Адда абсолютно согласен), но никак не с точки зрения процессорной оптимизации (т.к. то, что возможно убыстрит для одной платформы, может ухудшить производительность для другой платформы).
-
- Уже с Приветом
- Posts: 17281
- Joined: 07 Sep 2011 10:05
- Location: Seattle, WA
Re: Google Recruiter
Так что все эти бенчмарки, показывающие, что array random access существенно медленней чем sequential могут убедить меня только, если мне выдать performance таблицы для комбинаций процессора, OS, версии OS, JVM, версии JVM (версия Hotspot, версия Dalvik, версия J2ME для конкретного процессора и т.п.). И вот запустив benchmark и опубликовав данные по десяткам таких конфигураций - я тогда поверю, что у Java медленней random access чем sequential access.
-
- Уже с Приветом
- Posts: 6969
- Joined: 26 Feb 2011 17:40
Re: Google Recruiter
Ответил в личку.
-
- Уже с Приветом
- Posts: 9035
- Joined: 25 Oct 2011 19:02
- Location: SVO->ORD->SFO
Re: Google Recruiter
Что медленнее? Последовательный доступ для процессора быстрее из-за специфики адресации. Я уже третий раз одно и то же повторяю, если вы еще не заметили. Для JVM - ХЗ. Еще раз, ответ был конкретному человеку на конкретный вопрос. Читаем внимательно. Что касательно оптимизации последовательного доступа за счет кеширования, то вопрос надо рассматривать в частном случае.Zorkus wrote: Так медленнее или не медленнее? Да или нет?
-
- Уже с Приветом
- Posts: 6969
- Joined: 26 Feb 2011 17:40
Re: Google Recruiter
Не кипятитесь, может я не заметил чего просто. Вопрос вообще был как пример с моей стороны, потом в него все вцепились (простой вопрос видно, да),
Изначально вопрос был не про адресацию вообще, если вы отвечаете про адресацию - извините. Вопрос был такой "Почему в Java доступ к массиву int[] размером в тысячу элементов последовательный доступ намного быстрее, чем рандомный".
Изначально вопрос был не про адресацию вообще, если вы отвечаете про адресацию - извините. Вопрос был такой "Почему в Java доступ к массиву int[] размером в тысячу элементов последовательный доступ намного быстрее, чем рандомный".
-
- Уже с Приветом
- Posts: 9035
- Joined: 25 Oct 2011 19:02
- Location: SVO->ORD->SFO
Re: Google Recruiter
Про что вопрос был в самом начале - я понял. Объяснение с точки зрения механики работы процессора (адрессация и prefetching кеша) достатчно, чтобы покрыть x2-3 проигрышь. Откуда там x9 - это уже пусть желающие смотрят в код, генерируемый hotspot'ом.Zorkus wrote: Изначально вопрос был не про адресацию вообще, если вы отвечаете про адресацию - извините. Вопрос был такой "Почему в Java доступ к массиву int[] размером в тысячу элементов последовательный доступ намного быстрее, чем рандомный".
-
- Уже с Приветом
- Posts: 117
- Joined: 01 Sep 2004 09:52
Re: Google Recruiter
upd. Не туда посмотрел сначала.dotcom wrote:грубо говоря, несколько операций ldr r0, addr будут медленнее ldr r0, [r1, #offset]
Там не менее для ARM7TDMI в пределах 4К от базового регистра будет одинаковое время для последовательного и случайного доступа.
-
- Уже с Приветом
- Posts: 6969
- Joined: 26 Feb 2011 17:40
Re: Google Recruiter
О, come on. Там не в x9 раз, там вообще нет разницы никакой. Ладно, идея была в том, что вопрос должен провоцировать много вопросов, по которым можно оценивать реальный жизненный опыт кандидата. А не вопрос типа FizzBuzz.dotcom wrote:Про что вопрос был в самом начале - я понял. Объяснение с точки зрения механики работы процессора (адрессация и prefetching кеша) достатчно, чтобы покрыть x2-3 проигрышь. Откуда там x9 - это уже пусть желающие смотрят в код, генерируемый hotspot'ом.Zorkus wrote: Изначально вопрос был не про адресацию вообще, если вы отвечаете про адресацию - извините. Вопрос был такой "Почему в Java доступ к массиву int[] размером в тысячу элементов последовательный доступ намного быстрее, чем рандомный".
-
- Уже с Приветом
- Posts: 9035
- Joined: 25 Oct 2011 19:02
- Location: SVO->ORD->SFO
Re: Google Recruiter
Вы сами то читали вопрос по вашему линку? Результат тестового прогона:
Сколько будет, если поделить 450/50?Sum = 5002310.789580735 in 50 milliseconds
Sum = 5002310.789580964 in 450 milliseconds
Sum = 5002310.789580735 in 51 milliseconds
Sum = 5002310.789580964 in 478 milliseconds
-
- Уже с Приветом
- Posts: 9035
- Joined: 25 Oct 2011 19:02
- Location: SVO->ORD->SFO
Re: Google Recruiter
Для одной операции - понятно. А для цикла? Prediction block у него на столко тупой, что в цикле будет каждый раз offset читать из памяти?swimmer wrote:upd. Не туда посмотрел сначала.dotcom wrote:грубо говоря, несколько операций ldr r0, addr будут медленнее ldr r0, [r1, #offset]
Там не менее для ARM7TDMI в пределах 4К от базового регистра будет одинаковое время для последовательного и случайного доступа.
-
- Уже с Приветом
- Posts: 117
- Joined: 01 Sep 2004 09:52
Re: Google Recruiter
Там смещение либо регистр включен прямо в тело команды, так что никакого предсказания, похоже, нет.dotcom wrote:Для одной операции - понятно. А для цикла? Prediction block у него на столко тупой, что в цикле будет каждый раз offset читать из памяти?
Я смотрел на стр 4-26 http://cseweb.ucsd.edu/~kastner/cse30/a ... ionset.pdf
В общем для меня совершенно не очевидно что последовательный доступ всегда будет быстрее случайного.
-
- Уже с Приветом
- Posts: 3647
- Joined: 23 May 2010 15:10
Re: Google Recruiter
совсем мимоdotcom wrote:Кэшь то как раз не важен. Важнее метод адресации. В random нам адрес надо загружать сам адрес перед чтением или записью. При последовательном доступе используем регистр и оффсет, который грузится один раз. Т.е., грубо говоря, несколько операций ldr r0, addr будут медленнее ldr r0, [r1, #offset] Ну и SIMD тоже можно вспомнить для порядка. На кеш я бы особо не рассчитывал. Не факт, что процессор будет грузить пачку последовательных слов в кешь на всякий пожарный. Зависит от размера участка памяти, блока предсказаний. Загрузка данных в кешь тоже имеет цену.swimmer wrote:А вот мне как железячнику интересно стало. Возьмем к примеру процессор ARM с внешней SRAM (один кусок, никаких страниц) и оключим кэширование для этой памяти. Неужели в JAVA последовательный доступ будет быстрее случайного?Zorkus wrote:Сейчас придут железячники и С++-ники и вас заклюют
как раз таки кеш и важен, включая prefetcher
загрузить адрес в регистр - это копейки по сравнению cache miss и tlb miss
-
- Уже с Приветом
- Posts: 3647
- Joined: 23 May 2010 15:10
Re: Google Recruiter
не из-за специфики адресации, а из-за кеша и префетчаdotcom wrote:Что медленнее? Последовательный доступ для процессора быстрее из-за специфики адресации. Я уже третий раз одно и то же повторяю, если вы еще не заметили. Для JVM - ХЗ. Еще раз, ответ был конкретному человеку на конкретный вопрос. Читаем внимательно. Что касательно оптимизации последовательного доступа за счет кеширования, то вопрос надо рассматривать в частном случае.Zorkus wrote: Так медленнее или не медленнее? Да или нет?
последовательно - префетч - загрузит пару строк заранее, на одной строке кеша - 64 (cache line size) /4 (sizeof int) = 16 элементов, доступ к L1D - 3-4 такта в зависимости от того, к какому байту обращаемся и "других обстоятельств" (с)
+ нужно только 1 раз транслировать виртульный адрес в физический на 4096 (sizeof page) / 4 (sizeof int) = 1024 элемента
рандомно: - префетч нифига не загрузит = 100 тактов на cache miss и загрузку и памяти + если на другой странице и нету в tlb cache записи - еще и адрес надо транслировать = почитать table directory процесса = опять почитать память, что дорого
если элементов всего лишь 1000 (sizeof(int) * 1000 = 4000 < 4096 (page size)) - повезло, транслировать адрес нужно будет только 1 раз (ну 2 максимум, если на стыке страниц попали), также мы помещаемся в L1D (32К) - поэтому все элементы будут в кеше после разогрева
итого для частного случая получается: что если мы сначало заполнили массив из 1000 элементов, а потом сразу по нему побежали, то разницы быть не должно, так как все равно все лежит в L1D
если мы подготовили массив из 1000 элементов, а потом выкинули их из кеша, то разница будет на величину, которую обеспечивает hardware prefetcher
по поводу ужосов операционной системы: алгоритм своповании страниц в Window и Linux - LRU - поэтому страницы по которым бегаем ни под какой своп не попадут, более того, даже если "оно" начнет что-то свопить - то это никакого отношения к процессору не имеет, а на чистом эксперименте (без каких-то внешних приложений) его вообще не будет
насколько я знаю ни CLR ни JVM не запустят сборку мусора если не выделяется память и нет сторонних приложний, которые активно выделяют память (CLR подвешивается на события винды по поводу памяти (CreateMemoryResourceNotification) и если ее становится мало (стороннее приложение активно выделяет память), collect таки дергается), так что этого тоже не будет
-
- Уже с Приветом
- Posts: 3647
- Joined: 23 May 2010 15:10
Re: Google Recruiter
+1, by the way, часть тех, кто не стал менеджерами, стали "экспертами"avitya wrote:Вы невероятно неправы в этом.adda_ wrote: Тогда надо говорить досвидания. Потому что проверять умение писать код у человека который дцать лет его пишет глупо. За это время не умеющие писать код давно стали менеджерами.
-
- Уже с Приветом
- Posts: 15242
- Joined: 01 Mar 2007 05:18
- Location: VVO->ORD->DFW->SFO->DFW->PDX
Re: Google Recruiter
По-вашему, вопрос "почему луна больше солнца?" провоцирует много вопросов, по которым можно оценивать познания в астрономии?Zorkus wrote:Ладно, идея была в том, что вопрос должен провоцировать много вопросов, по которым можно оценивать реальный жизненный опыт кандидата. А не вопрос типа FizzBuzz.
При этом с луной-солнцем все более-менее однозначно, а в вашем вопросе все гораздо хуже. Потому что действительно может быть быстрее, а может и не быть. И вместо нормальных рассуждений что на что и как может влиять, интервьюируемый будет заниматься гаданием, что же от него хотят услышать
Тут же какая фишка. Средний нормальный человек имеет свойство сомневаться. Он сомневается, что правильно понял вопрос, он допускает, что вполне очевидный и правильный ответ, который у него сразу появился в голове - правильный. В конце концов, вполне нормально сомневаться в том, что задающий вопрос действительно знает правильный ответ, а не верит в какой-то миф. И когда психологические вопросы соединяются с вопросом, в который заложено слишком много неоднозначностей, результат получается практически случайный
Мат на форуме запрещен, блдж!
-
- Уже с Приветом
- Posts: 6969
- Joined: 26 Feb 2011 17:40
Re: Google Recruiter
А вы сами не обратили внимание, что в данном тесте бенчмаркер использует массив из 1 000 000 элементов, а вопрос был про 1000? А двумя постами ниже в треде тот же самый автор пишет:dotcom wrote:Вы сами то читали вопрос по вашему линку? Результат тестового прогона:Сколько будет, если поделить 450/50?Sum = 5002310.789580735 in 50 milliseconds
Sum = 5002310.789580964 in 450 milliseconds
Sum = 5002310.789580735 in 51 milliseconds
Sum = 5002310.789580964 in 478 milliseconds
До туда вы уже не дочитали?When I use SIZE = 1000 in that code (and a suitably larger number of repeats in the "time" method) then contrary to the statement in the original post, I don't see a significant difference between the sequential access and the random access. (So my answer was technically correct -- there isn't a difference for arrays with 1000 elements. Not in my tests anyway.)
But when I use SIZE = 10000 I do see a significant difference (50% longer for random access). So the reason depends on the size of the array. The larger the array, the bigger the difference.
-
- Уже с Приветом
- Posts: 3647
- Joined: 23 May 2010 15:10
Re: Google Recruiter
скиньте мне тоже плиз, интересноZorkus wrote: Послал вам в личку еще пару примеров того, что я считаю хорошими вопросами по Java / JVM. Сорри, что пока в личку.
-
- Уже с Приветом
- Posts: 10708
- Joined: 22 Jul 2006 20:19
Re: Google Recruiter
Я вообще не понимаю ничего. Если для задачи критично время доступа к элементу массива размером в 1000 штуков то надо использовать какой то другой язык вместо Жабы. Языки высокого уровня особенно те которые крос платформенные (или имеют претензии на это) не предназначены для задач реального времени где счет идет на милисекунды.. Т.е. вопрос вообще не имеет никакого практического смысла.. И говорит о кругозоре вопрошающего... Вспоминается известная басня Крылова.Zorkus wrote: А вы сами не обратили внимание, что в данном тесте бенчмаркер использует массив из 1 000 000 элементов, а вопрос был про 1000? А двумя постами ниже в треде тот же самый автор пишет:
До туда вы уже не дочитали?
-
- Уже с Приветом
- Posts: 3647
- Joined: 23 May 2010 15:10
Re: Google Recruiter
by the way, автор сего "бенчмарка" (того, что по ссылке)
читает одновременно из двух массивов,
один - indexes (всегда последовательно),
второй - data
благо, x86 имеют префетчер, который может более одного потока данных одновременно префетчить, так что на x86 будет все хорошо, но не факт, что также будет хорошо на других платформах
+он считает сумму, типа double, на x86 2 порта могут складывать double одновременно, поэтому unrollнув цикл на 2 (т.е. 2 сумматора чтобы были) было бы быстрее (если данные уже в кеше, хотя вообще непонятно зачем он сумму считает, достаточно было бы просто прочитать вникуда (предварительно убрав оптимизацию у jittера), был бы чище эксперимент)
т.е. бенчмарк хоть и показывает какие-то цифры по последовательному/параллельному доступу, но сказать, что чистый эксперимент никак нельзя
private double sum(Integer[] indexes) {
double sum = 0.0;
for (Integer i: indexes) {
sum += data;
}
return sum;
}
читает одновременно из двух массивов,
один - indexes (всегда последовательно),
второй - data
благо, x86 имеют префетчер, который может более одного потока данных одновременно префетчить, так что на x86 будет все хорошо, но не факт, что также будет хорошо на других платформах
+он считает сумму, типа double, на x86 2 порта могут складывать double одновременно, поэтому unrollнув цикл на 2 (т.е. 2 сумматора чтобы были) было бы быстрее (если данные уже в кеше, хотя вообще непонятно зачем он сумму считает, достаточно было бы просто прочитать вникуда (предварительно убрав оптимизацию у jittера), был бы чище эксперимент)
т.е. бенчмарк хоть и показывает какие-то цифры по последовательному/параллельному доступу, но сказать, что чистый эксперимент никак нельзя
-
- Уже с Приветом
- Posts: 3647
- Joined: 23 May 2010 15:10
Re: Google Recruiter
все нормально в кругозоре у вопрощающего, минимум потому что для конкретно этой задачи java генерит ничуть не хуже код, чем сгенерил бы C\С++adda_ wrote:Я вообще не понимаю ничего. Если для задачи критично время доступа к элементу массива размером в 1000 штуков то надо использовать какой то другой язык вместо Жабы. Языки высокого уровня особенно те которые крос платформенные (или имеют претензии на это) не предназначены для задач реального времени где счет идет на милисекунды.. Т.е. вопрос вообще не имеет никакого практического смысла.. И говорит о кругозоре вопрошающего... Вспоминается известная басня Крылова.Zorkus wrote: А вы сами не обратили внимание, что в данном тесте бенчмаркер использует массив из 1 000 000 элементов, а вопрос был про 1000? А двумя постами ниже в треде тот же самый автор пишет:
До туда вы уже не дочитали?
во вторых задача на поговорить, а не на реализовать HFT на жабе
-
- Уже с Приветом
- Posts: 6969
- Joined: 26 Feb 2011 17:40
Re: Google Recruiter
Скинул парочку еще.Alexandr wrote:скиньте мне тоже плиз, интересноZorkus wrote: Послал вам в личку еще пару примеров того, что я считаю хорошими вопросами по Java / JVM. Сорри, что пока в личку.
-
- Уже с Приветом
- Posts: 9035
- Joined: 25 Oct 2011 19:02
- Location: SVO->ORD->SFO
Re: Google Recruiter
Вам не приходило в голову, что загрузка адреса в регистр - это абсолютно такая же операция, как загрузка данных в регистр? Cache miss и TLB будут работать абсолютно одинаково по скорости. Да, через страницы скакать всегда дороже. Но мы этого вопроса не касались. Хотя особенно продвинутые уже дошли до swap'а. Prefetcher контролируется branch/execution prediction модулем.Alexandr wrote: загрузить адрес в регистр - это копейки по сравнению cache miss и tlb miss
На x86 оно, скорее, действительно упирается в производительность операций. Скажем, имеем бесполезный цикл:
Code: Select all
loop:
mov eax, [esi + ebx]
add ebx, 4
cmp ebx, high_bound
jbe loop
Last edited by dotcom on 03 Sep 2012 20:11, edited 1 time in total.
-
- Уже с Приветом
- Posts: 9035
- Joined: 25 Oct 2011 19:02
- Location: SVO->ORD->SFO
Re: Google Recruiter
Читал. Был смущен вашим же комментарием про значительную разницу.Zorkus wrote: До туда вы уже не дочитали?
-
- Уже с Приветом
- Posts: 6969
- Joined: 26 Feb 2011 17:40
Re: Google Recruiter
Так я же специально ввел в заблуждениеdotcom wrote:Читал. Был смущен вашим же комментарием про значительную разницу.Zorkus wrote: До туда вы уже не дочитали?
-
- Уже с Приветом
- Posts: 3647
- Joined: 23 May 2010 15:10
Re: Google Recruiter
dotcom wrote:Вам не приходило в голову, что загрузка адреса в регистр - это абсолютно такая же операция, как загрузка данных в регистр? Cache miss и TLB будут работать абсолютно одинаково по скорости. Да, через страницы скакать всегда дороже. Но мы этого вопроса не касались. Хотя особенно продвинутые уже дошли до swap'а. Prefetcher контролируется branch/execution prediction модулем.Alexandr wrote: загрузить адрес в регистр - это копейки по сравнению cache miss и tlb miss
На x86 оно, скорее, действительно упирается в производительность операций. Скажем, имеем бесполезный цикл:Все дешевые операции, которые выполняются за такт (на самом деле, меньше чем за такт даже). Команды засосутся в ALU за раз, считывать их каждый раз из памяти/кеша нет смысла. Остается только читать [esi + ebx]. Да, тут задача для предсказателя простая. Главное, чтобы он не подумал чего лишнего про сам цикл. Если же туда вставить random access операцию, то он подумает, что "ну его на фиг", потому как память читать надо будет много и из разных мест.Code: Select all
loop: mov eax, [esi + ebx] add ebx, 4 cmp ebx, high_bound jbe loop
загрузка адресаВам не приходило в голову, что загрузка адреса в регистр - это абсолютно такая же операция, как загрузка данных в регистр?
mov eax, const - вообще никакого обращения к памяти, константа лежит как часть инструкции (mov + immidiate)
загрузка данных по адресу -
mov eax, [esi] - обращение к памяти по адресу, указывающему esi
вы скорее всего имеете ввиду случай, когда загружаемый адрес хранится в другой переменной, но к чему такая сложность
можно рассуждать далее в стиле, что при адресации base + offset выполняться будет чуть быстрее, чем например base + index (см. интелловскую документацию), просто все это влияет на данный пример в гораздо меньшей степени, чем всякие issues с кешем
я там выше писал - не будет никакого свопа, уже не говоря о том, что своп не задействует процессор (после того как irp сгенерился и скинулся драйверу,а тот инициировал запись на диск)Хотя особенно продвинутые уже дошли до swap'а.
это совсем совсем не правда, префетчер вообще никакого отношения не имеет к branch predictionPrefetcher контролируется branch/execution prediction модулем.
неа, в доступ по памяти оно скорее всего упрется, т.е. банально будут циклы простоя процессораНа x86 оно, скорее, действительно упирается в производительность операций.
во-первых, команды не хранятся в ALU несколько итераций, максимум где они хранятся это mop-cache внутри процессора (что-то вроде 128 байт) и то, только у sandy bridge (и то с большими оговорками), но речь вообще не о командах, а о данных, которые мы читаемКоманды засосутся в ALU за раз, считывать их каждый раз из памяти/кеша нет смысла.
это в лучшем случае, в худшем - зачитает то, что "посчитает нужным", что для нас хуже, чем если бы вообще не читалЕсли же туда вставить random access операцию, то он подумает, что "ну его на фиг", потому как память читать надо будет много и из разных мест.