КомпьютGPU GRPU Compute Framework для графических карт поставщика поставщика (AMD, Qualcomm, Nvidia & Friends) |
Присоединяйтесь к звонкам Discord & Community? Документационная запись в блоге ⌨ Примеры?
Ниже вы можете найти пример умножения графического процессора, используя интерфейсы C ++ и Python Kompute.
Вы можете присоединиться к Discord для вопросов / обсуждения, открыть проблему GitHub или прочитать документацию.
Интерфейс C ++ обеспечивает низкий уровень доступа к нативным компонентам Kompute, что позволяет расширенной оптимизации, а также расширение компонентов.
void kompute ( const std::string& shader) {
// 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
kp::Manager mgr;
// 2. Create and initialise Kompute Tensors through manager
// Default tensor constructor simplifies creation of float values
auto tensorInA = mgr. tensor ({ 2 ., 2 ., 2 . });
auto tensorInB = mgr. tensor ({ 1 ., 2 ., 3 . });
// Explicit type constructor supports uint32, int32, double, float and bool
auto tensorOutA = mgr. tensorT < uint32_t >({ 0 , 0 , 0 });
auto tensorOutB = mgr. tensorT < uint32_t >({ 0 , 0 , 0 });
std::vector<std::shared_ptr<kp::Memory>> params = {tensorInA, tensorInB, tensorOutA, tensorOutB};
// 3. Create algorithm based on shader (supports buffers & push/spec constants)
kp::Workgroup workgroup ({ 3 , 1 , 1 });
std::vector< float > specConsts ({ 2 });
std::vector< float > pushConstsA ({ 2.0 });
std::vector< float > pushConstsB ({ 3.0 });
auto algorithm = mgr. algorithm (params,
// See documentation shader section for compileSource
compileSource (shader),
workgroup,
specConsts,
pushConstsA);
// 4. Run operation synchronously using sequence
mgr. sequence ()
-> record <kp::OpSyncDevice>(params)
-> record <kp::OpAlgoDispatch>(algorithm) // Binds default push consts
-> eval () // Evaluates the two recorded operations
-> record <kp::OpAlgoDispatch>(algorithm, pushConstsB) // Overrides push consts
-> eval (); // Evaluates only last recorded operation
// 5. Sync results from the GPU asynchronously
auto sq = mgr. sequence ();
sq-> evalAsync <kp::OpSyncLocal>(params);
// ... Do other work asynchronously whilst GPU finishes
sq-> evalAwait ();
// Prints the first output which is: { 4, 8, 12 }
for ( const float & elem : tensorOutA-> vector ()) std::cout << elem << " " ;
// Prints the second output which is: { 10, 10, 10 }
for ( const float & elem : tensorOutB-> vector ()) std::cout << elem << " " ;
} // Manages / releases all CPU and GPU memory resources
int main () {
// Define a raw string shader (or use the Kompute tools to compile to SPIRV / C++ header
// files). This shader shows some of the main components including constants, buffers, etc
std::string shader = ( R"(
#version 450
layout (local_size_x = 1) in;
// The input tensors bind index is relative to index in parameter passed
layout(set = 0, binding = 0) buffer buf_in_a { float in_a[]; };
layout(set = 0, binding = 1) buffer buf_in_b { float in_b[]; };
layout(set = 0, binding = 2) buffer buf_out_a { uint out_a[]; };
layout(set = 0, binding = 3) buffer buf_out_b { uint out_b[]; };
// Kompute supports push constants updated on dispatch
layout(push_constant) uniform PushConstants {
float val;
} push_const;
// Kompute also supports spec constants on initalization
layout(constant_id = 0) const float const_one = 0;
void main() {
uint index = gl_GlobalInvocationID.x;
out_a[index] += uint( in_a[index] * in_b[index] );
out_b[index] += uint( const_one * push_const.val );
}
)" );
// Run the function declared above with our raw string shader
kompute (shader);
}
Пакет Python обеспечивает интерактивный интерфейс высокого уровня, который обеспечивает эксперименты, обеспечивая при этом высокопроизводительные и быстрые рабочие процессы разработки.
from . utils import compile_source # using util function from python/test/utils
def kompute ( shader ):
# 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
mgr = kp . Manager ()
# 2. Create and initialise Kompute Tensors through manager
# Default tensor constructor simplifies creation of float values
tensor_in_a = mgr . tensor ([ 2 , 2 , 2 ])
tensor_in_b = mgr . tensor ([ 1 , 2 , 3 ])
# Explicit type constructor supports uint32, int32, double, float and bool
tensor_out_a = mgr . tensor_t ( np . array ([ 0 , 0 , 0 ], dtype = np . uint32 ))
tensor_out_b = mgr . tensor_t ( np . array ([ 0 , 0 , 0 ], dtype = np . uint32 ))
assert ( t_data . data_type () == kp . DataTypes . uint )
params = [ tensor_in_a , tensor_in_b , tensor_out_a , tensor_out_b ]
# 3. Create algorithm based on shader (supports buffers & push/spec constants)
workgroup = ( 3 , 1 , 1 )
spec_consts = [ 2 ]
push_consts_a = [ 2 ]
push_consts_b = [ 3 ]
# See documentation shader section for compile_source
spirv = compile_source ( shader )
algo = mgr . algorithm ( params , spirv , workgroup , spec_consts , push_consts_a )
# 4. Run operation synchronously using sequence
( mgr . sequence ()
. record ( kp . OpTensorSyncDevice ( params ))
. record ( kp . OpAlgoDispatch ( algo )) # Binds default push consts provided
. eval () # evaluates the two recorded ops
. record ( kp . OpAlgoDispatch ( algo , push_consts_b )) # Overrides push consts
. eval ()) # evaluates only the last recorded op
# 5. Sync results from the GPU asynchronously
sq = mgr . sequence ()
sq . eval_async ( kp . OpTensorSyncLocal ( params ))
# ... Do other work asynchronously whilst GPU finishes
sq . eval_await ()
# Prints the first output which is: { 4, 8, 12 }
print ( tensor_out_a )
# Prints the first output which is: { 10, 10, 10 }
print ( tensor_out_b )
if __name__ == "__main__" :
# Define a raw string shader (or use the Kompute tools to compile to SPIRV / C++ header
# files). This shader shows some of the main components including constants, buffers, etc
shader = """
#version 450
layout (local_size_x = 1) in;
// The input tensors bind index is relative to index in parameter passed
layout(set = 0, binding = 0) buffer buf_in_a { float in_a[]; };
layout(set = 0, binding = 1) buffer buf_in_b { float in_b[]; };
layout(set = 0, binding = 2) buffer buf_out_a { uint out_a[]; };
layout(set = 0, binding = 3) buffer buf_out_b { uint out_b[]; };
// Kompute supports push constants updated on dispatch
layout(push_constant) uniform PushConstants {
float val;
} push_const;
// Kompute also supports spec constants on initalization
layout(constant_id = 0) const float const_one = 0;
void main() {
uint index = gl_GlobalInvocationID.x;
out_a[index] += uint( in_a[index] * in_b[index] );
out_b[index] += uint( const_one * push_const.val );
}
"""
kompute ( shader )Вы можете попробовать интерактивные ноутбуки Colab, которые позволяют использовать бесплатный графический процессор. Доступными примерами являются примеры Python и C ++ ниже:
Попробуйте интерактивную Colab C ++ из сообщения в блоге | Попробуйте интерактивный Python Colab из сообщения в блоге |
Вы также можете проверить две следующие переговоры, представленные на конференции Fosdem 2021.
Оба видео имеют метки времени, которые позволят вам пропустить наиболее релевантный раздел для вас - вступление и мотивация для обоих почти одинаковы, так что вы можете пропустить более конкретный контент.
Посмотрите видео для энтузиастов C ++ | Посмотрите видео для любителей Python & Machine Learning |
Основная архитектура Kompute включает в себя следующее:
Чтобы увидеть полную разбивку, вы можете прочитать дальше в ссылке на класс C ++.
| Полная архитектура | Упрощенные компоненты |
|---|---|
(Очень крошечный, проверьте полную справочную диаграмму в DOCS для получения подробной информации) |
Kompute обеспечивает гибкость для выполнения операций асинриховым способом через vk :: заборы. Кроме того, Kompute обеспечивает явное распределение очередей, что позволяет параллельно выполнять операции в семействах очередей.
Изображение ниже дает интуицию о том, как копютные последовательности могут быть выделены на разные очереди, чтобы обеспечить параллельное выполнение на основе аппаратного обеспечения. Вы можете увидеть пример в руки, а также подробную страницу документации, описывающую, как это будет работать с использованием NVIDIA 1650 в качестве примера.
Kompute был оптимизирован для работы в мобильных средах. Система сборки обеспечивает динамическую загрузку вульковской общей библиотеки для среды для Android, а также работающую обертку Android NDK для заголовков CPP.
Для полного глубокого погружения вы можете прочитать сообщение в блоге «Нагнетав ваши мобильные приложения с помощью ускоренного машинного обучения на графическом процессоре на графике». Вы также можете получить доступ к примеру кода в репозитории, который можно запустить с помощью Android Studio. |
Помимо сердечного SDK C ++, вы также можете использовать пакет Python Kompute, который раскрывает ту же основную функциональность и поддерживает совместимость с объектами Python, такими как списки, массивы Numpy и т. Д.
Единственными зависимостями являются Python 3.5+ и Cmake 3.4.1+. Вы можете установить Kompute из пакета Python PYPI, используя следующую команду.
pip install kp
Вы также можете установить из главной ветви, используя:
pip install git+git://github.com/KomputeProject/kompute.git@master
Для получения дополнительной информации вы можете прочитать документацию Python Package или справочную документацию Python Class.
Предоставленная система сборки использует cmake , который позволяет создавать поперечные сборки.
Makefile верхнего уровня предоставляет набор оптимизированных конфигураций для разработки, а также сборка изображения Docker, но вы можете запустить сборку с следующей командой:
cmake -Bbuild
Вы также можете добавить Kompute в свой репо с помощью add_subdirectory - файл Android пример cmakelists.txt показывает, как это будет сделано.
Для более продвинутого обзора конфигурации сборки ознакомьтесь с документацией System Build System Deep Dive.
Мы ценим PR и проблемы. Если вы хотите внести свой вклад, попробуйте проверить тег «Хороший первый выпуск», но даже использование проблем Kompute и отчетности - отличный вклад!
Если вы хотите запустить с слоями отладки, вы можете добавить их с параметрами KOMPUTE_ENV_DEBUG_LAYERS как:
export KOMPUTE_ENV_DEBUG_LAYERS="VK_LAYER_LUNARG_api_dump"
Чтобы обновить документацию, вам нужно:
make push_docs_to_ghpages Запуск модульных тестов был значительно упрощен для участников.
Тесты запускаются на процессоре и могут быть запускаются с помощью интерфейса командной строки ACT (https://github.com/nektos/act) - как только вы установите командную строку (и запустите Docker Daemon), вам просто нужно ввести:
$ act
[Python Tests/python-tests] Start image=axsauze/kompute-builder:0.2
[C++ Tests/cpp-tests ] Start image=axsauze/kompute-builder:0.2
[C++ Tests/cpp-tests ] ? docker run image=axsauze/kompute-builder:0.2 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[Python Tests/python-tests] ? docker run image=axsauze/kompute-builder:0.2 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
...
Репозиторий содержит модульные тесты для кода C ++ и Python и может быть найден в папке test/ и python/test .
Тесты в настоящее время проходят через CI с использованием действий GitHub. Он использует изображения, найденные в docker-builders/ .
Чтобы минимизировать аппаратные требования, тесты могут выполняться без графического процессора, непосредственно в процессоре с использованием Swiftshader.
Для получения дополнительной информации о том, как настроены CI и тесты, вы можете перейти в раздел CI, Docker и Tests в документации.
Этот проект начался после того, как увидел, что многие новые и известные проекты ML & DL, такие как Pytorch, Tensorflow, Alibaba DNN, Tencent NCNN - среди прочего - имеют либо интегрированные, либо стремятся интегрировать Vulkan SDK, чтобы добавить поддержку мобильного (и кросс -поставщика).
Vulkan SDK предлагает отличный интерфейс низкого уровня, который обеспечивает высокоспециализированные оптимизации - однако он поставляется по цене очень многословного кода, который требует 500-2000 строк кода, чтобы даже начать написание кода приложения. Это привело к тому, что каждый из этих проектов должен был реализовать один и тот же базовый уровень, чтобы абстрагировать некомпентические связанные особенности Вулканского SDK. Такое большое количество нестандартно-котлом может привести к ограниченному передаче знаний, более высокой вероятности уникальных платежных ошибок в реализации и т. Д.
В настоящее время мы разрабатываем Kompute не для того, чтобы скрывать интерфейс Vulkan SDK (как это невероятно хорошо спроектировано), но чтобы увеличить его с прямым акцентом на вычисления GPU Vulkan SDK. Эта статья содержит обзор мотивации Kompute, а также набор примеров, которые вводят как вычисления GPU, так и основную архитектуру Kompute.