«Я читал, что машины F1 быстрее, чем те, которые мы едем на улицах ... почему люди тогда не используют машины F1?» Что ж ... Ответ на этот вопрос прост: машины F1 не могут ломаться или поворачивать так быстро, как большинство машин (в этом случае самая медленная машина может побить F1). Случай с графическими процессорами очень похож, они хорошо следуют по прямой линии обработки, но они не так хороши, когда дело доходит до выбора различных путей обработки.
Программа, выполняемая в графическом процессоре, имеет смысл, когда она должна выполняться много раз параллельно, например, когда вам нужно смешать все пиксели из текстуры A с пикселями из текстуры B и поместить их все в текстуру C. Эта задача, когда выполняется в процессор, будет обрабатываться как-то так:
for( int i =0; i< nPixelCount; i++ )
TexC[i] = TexA[i] + TexB[i];
Но это медленно, когда вам приходится обрабатывать много пикселей, поэтому графический процессор вместо того, чтобы использовать приведенный выше код, просто использует следующий:
TexC[i] = TexA[i] + TexB[i];
и затем он заполняет все ядра этой программой (по существу, копируя программу в ядро), назначая значение i
для каждого. Тогда вот откуда приходит волшебство от графического процессора и заставляет все ядра выполнять программу одновременно , выполняя множество операций намного быстрее, чем могла бы выполнять программа линейного процессора.
Этот способ работы подходит для тех случаев, когда вам приходится обрабатывать очень много небольших входных данных, но на самом деле это плохо, когда вам нужно создать программу, которая может иметь условное ветвление. Итак, теперь давайте посмотрим, что делает процессор, когда дело доходит до некоторой проверки состояния:
- 1: выполнить программу до первой логической операции
- 2: оценить
- 3: Продолжить выполнение из адреса памяти результата сравнения (как с инструкцией asm JNZ)
Это очень быстро для CPU, как установка индекса, но для GPU сделать то же самое, это намного сложнее. Поскольку питание от графического процессора происходит от выполнения одной и той же инструкции в одно и то же время (они являются ядрами SIMD), они должны быть синхронизированы, чтобы использовать преимущества архитектуры чипа. Необходимость подготовки графического процессора для работы с филиалами подразумевает более или менее:
- 1: Сделайте версию программы, которая следует только за ветвью A, заполните этот код во всех ядрах.
- 2: выполнить программу до первой логической операции
- 3: Оценить все элементы
- 4: Продолжить обработку всех элементов, которые следуют за веткой A, поставить в очередь все процессы, которые выбрали путь B (для которого нет программы в ядре!). Теперь все те ядра, которые выбрали путь B, будут бездействовать !! - наихудший случай - выполнение одного ядра и ожидание любого другого ядра.
- 5: Как только все As закончили обработку, активируйте версию программы ветви B (скопировав ее из буферов памяти в небольшую память ядра).
- 6: Выполнить ветку B.
- 7: при необходимости смешать / объединить оба результата.
Этот метод может варьироваться в зависимости от многих вещей (например, некоторые очень маленькиеветки могут работать без необходимости этого различия), но теперь вы уже можете видеть, почему ветвление будет проблемой. Кэши GPU очень малы, вы не можете просто выполнить программу из VRAM линейным способом, она должна копировать небольшие блоки инструкций в ядра, которые будут выполняться, и если у вас достаточно веток, ваш GPU будет в основном остановлен, чем выполнение любой код, который не имеет смысла, когда он возникает при выполнении программы, которая следует только за одной ветвью, как это делает большинство программ - даже если она выполняется в нескольких потоках. По сравнению с примером F1 это похоже на то, что нужно открывать тормозные парашюты в каждом углу, а затем выйти из машины, чтобы упаковать их обратно в машину до следующего поворота, который вы хотите повернуть снова, или найти красный семафор (следующий угол наверняка).
Тогда, конечно же, существует проблема того, что другие архитектуры так хорошо справляются с задачей логических операций, гораздо дешевле и надежнее, стандартизированы, лучше известны, энергоэффективны и т. Д. Более новые видеокарты вряд ли совместимы со старыми без эмуляции программного обеспечения, они использовать разные ассемблерные инструкции между ними, даже если они принадлежат одному и тому же производителю, и что в настоящее время большинству компьютерных приложений не требуется этот тип параллельной архитектуры, и даже если они им понадобятся, они могут использовать стандартные API, такие как OpenCL, как упомянутый eBusiness, или через графический интерфейс API. Возможно, через несколько десятилетий у нас появятся графические процессоры, которые смогут заменить процессоры, но я не думаю, что это произойдет в ближайшее время.
Я рекомендую документацию от AMD APP, которая многое объясняет об их архитектуре GPU, и я также видел о NVIDIA в руководствах по CUDA, которые мне очень помогли в понимании этого. Я до сих пор не понимаю некоторые вещи, и я могу ошибаться, возможно, кто-то, кто знает больше, может подтвердить или опровергнуть мои заявления, что было бы здорово для всех нас.