Рассматривайте ваше ядро как функцию, выполняющую работу CBC.Как вы выяснили, его цепная природа означает, что сама задача CBC принципиально сериализована.Кроме того, графический процессор предпочитает запускать 16 потоков с одинаковыми рабочими нагрузками.По сути, это размер одной задачи в многопроцессорном ядре, которых, как правило, десятки;но система управления может выполнять только некоторые из этих задач в целом, и система памяти редко справляется с ними.Кроме того, циклы являются одним из худших вариантов использования ядра, поскольку графические процессоры не предназначены для выполнения большого потока управления.
Итак, глядя на AES, он работает с 16-байтовыми блоками, но только в байтовых операциях.Это будет ваше первое измерение - каждый блок должен быть обработан 16 потоками (вероятно, локальный размер работы на языке opencl).Обязательно перенесите блок в локальную память, где все потоки могут работать в режиме блокировки, делая произвольный доступ с очень низкой задержкой.Разверните все в операции блока AES, используя get_local_id (0), чтобы узнать, с каким байтом работает каждый поток.Синхронизировать с барьером (CLK_LOCAL_MEM_FENCE) в случае, если рабочая группа работает на процессоре, который может выйти из режима блокировки.Ключ, вероятно, может быть сохранен в постоянной памяти, поскольку он может быть кэширован.Цепочка блоков может быть подходящим уровнем для цикла, хотя бы для того, чтобы избежать перезагрузки предыдущего зашифрованного текста блока из глобальной памяти.Также может помочь асинхронное сохранение завершенного зашифрованного текста с использованием async_work_group_copy ().Возможно, вы можете заставить поток выполнять больше работы, используя векторы, но это, вероятно, не поможет из-за таких шагов, как shiftRows.
В принципе, если какой-либо поток в группе из 16 потоков (может отличаться в зависимости от архитектуры) получает какой-либо другой поток управления, ваш графический процессор останавливается.И если таких групп недостаточно для заполнения конвейеров и мультипроцессоров, ваш графический процессор бездействует.Пока вы не очень тщательно оптимизируете доступ к памяти, он не приблизится к скорости процессора, и даже после этого вам нужно будет обрабатывать десятки пакетов одновременно, чтобы избежать создания слишком маленьких рабочих групп для GPU.Проблема заключается в том, что, хотя графический процессор может выполнять тысячи потоков, его структура управления в любое время обрабатывает только несколько рабочих групп.
Еще одна вещь, о которой следует опасаться;когда вы используете барьеры в рабочей группе, каждый поток в рабочей группе должен выполнять одни и те же вызовы барьера.Это означает, что даже если у вас есть дополнительные потоки, работающие вхолостую (например, те, которые дешифруют более короткий пакет в объединенной рабочей группе), они должны продолжать проходить цикл, даже если у них нет доступа к памяти.