Kompute크로스 공급 업체 그래픽 카드를위한 범용 GPU 컴퓨팅 프레임 워크 (AMD, Qualcomm, Nvidia & Friends) |
불화 및 커뮤니티 전화에 가입 하시겠습니까? 문서 블로그 게시물 ⌨ 예?
아래에서는 C ++ 및 Python Kompute 인터페이스를 사용하여 GPU 곱셈 예를 찾을 수 있습니다.
질문 / 토론을 위해 불화에 참여하거나 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 )무료 GPU를 사용할 수있는 대화식 Colab 노트북을 시험해 볼 수 있습니다. 사용 가능한 예는 아래의 파이썬 및 C ++ 예입니다.
블로그 게시물에서 대화식 C ++ Colab을 사용해보십시오 | 블로그 게시물에서 대화식 Python Colab을 사용해보십시오 |
FOSDEM 2021 회의에서 발표 된 다음 두 회의를 확인할 수도 있습니다.
두 비디오 모두 타임 스탬프가있어 가장 관련성이 높은 섹션으로 건너 뛸 수 있습니다. 두 가지 소개 및 동기는 거의 동일하므로보다 구체적인 콘텐츠로 건너 뛸 수 있습니다.
C ++ 애호가를위한 비디오를보십시오 | Python & Machine Learning 애호가의 비디오를보십시오 |
Kompute의 핵심 아키텍처에는 다음이 포함됩니다.
전체 분석을 보려면 C ++ 클래스 참조에서 더 읽을 수 있습니다.
| 풀 아키텍처 | 단순화 된 Kompute 구성 요소 |
|---|---|
(매우 작고 자세한 내용은 문서에서 전체 참조 다이어그램을 확인하십시오) |
Kompute는 vk :: 펜스를 통해 비동기 방식으로 작업을 실행할 수있는 유연성을 제공합니다. 또한 Kompute를 사용하면 대기열을 명시 적으로 할당하여 큐 패밀리에 걸쳐 작업을 병렬로 실행할 수 있습니다.
아래 이미지는 하드웨어를 기반으로 병렬 실행을 가능하게하기 위해 Kompute 시퀀스를 다른 대기열에 할당하는 방법에 대한 직관을 제공합니다. 예를 들어 NVIDIA 1650을 예로 사용하는 방법을 설명하는 자세한 문서 페이지뿐만 아니라 예를 들어 손을 볼 수 있습니다.
Kompute는 모바일 환경에서 작동하도록 최적화되었습니다. 빌드 시스템을 사용하면 CPP 헤더 용 작업중인 Android NDK 래퍼와 함께 Android 환경을위한 Vulkan 공유 라이브러리의 동적로드가 가능합니다.
완전한 깊은 다이빙을 위해 블로그 게시물 "기기 GPU 가속 머신 러닝으로 모바일 앱을 과급하는 것"을 읽을 수 있습니다. 안드로이드 스튜디오를 사용하여 실행할 수있는 저장소의 엔드 투 엔드 예제 코드에 액세스 할 수도 있습니다. |
C ++ Core SDK 외에도 동일한 코어 기능을 노출시키는 Kompute의 Python 패키지를 사용할 수 있으며 Lists, Numpy Array 등과 같은 Python 객체와의 상호 운용성을 지원합니다.
유일한 종속성은 Python 3.5+ 및 CMake 3.4.1+입니다. 다음 명령을 사용하여 Python PYPI 패키지에서 Kompute를 설치할 수 있습니다.
pip install kp
다음을 사용하여 마스터 브랜치에서 설치할 수도 있습니다.
pip install git+git://github.com/KomputeProject/kompute.git@master
자세한 내용은 Python 패키지 문서 또는 Python Class 참조 문서를 읽을 수 있습니다.
제공된 빌드 시스템은 cmake 사용하여 크로스 플랫폼 빌드를 허용합니다.
최상위 레벨 Makefile Docker 이미지 빌드뿐만 아니라 개발을위한 최적화 된 구성 세트를 제공하지만 다음 명령으로 빌드를 시작할 수 있습니다.
cmake -Bbuild
또한 add_subdirectory -Android 예제 cmakelists.txt 파일을 사용하여 Repo에 Kompute를 추가 할 수 있습니다.
빌드 구성에 대한보다 고급 개요는 빌드 시스템 딥 다이브 문서를 확인하십시오.
PRS와 문제에 감사드립니다. "좋은 첫 번째 이슈"태그를 확인해 보지 않으려면 Kompute 및보고 문제를 사용해도 큰 기여를하십시오!
디버그 레이어로 실행하려면 KOMPUTE_ENV_DEBUG_LAYERS 매개 변수로 다음을 추가 할 수 있습니다.
export KOMPUTE_ENV_DEBUG_LAYERS="VK_LAYER_LUNARG_api_dump"
문서를 업데이트하려면 다음과 같은 것이 필요합니다.
make push_docs_to_ghpages 사용하여 github 페이지로 푸시하십시오 장치 테스트를 실행하는 것이 기여자에게는 상당히 단순화되었습니다.
테스트는 CPU에서 실행되며 ACT 명령 줄 인터페이스 (https://github.com/nektos/act)를 사용하여 트리거 될 수 있습니다.
$ 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 폴더에서 찾을 수 있습니다.
테스트는 현재 GitHub 작업을 사용하여 CI를 통해 실행됩니다. docker-builders/ 에서 발견 된 이미지를 사용합니다.
하드웨어 요구 사항을 최소화하기 위해 Swiftshader를 사용하여 CPU에서 GPU없이 테스트를 실행할 수 있습니다.
CI 및 테스트 설정 방법에 대한 자세한 내용은 문서의 CI, Docker 및 Tests 섹션으로 이동할 수 있습니다.
이 프로젝트는 Pytorch, Tensorflow, Alibaba DNN, Tencent NCNN과 같은 많은 새롭고 유명한 ML & DL 프로젝트가 Vulkan SDK를 모바일 (및 크로스 벤더) GPU 지원을 추가하기 위해 통합하거나 통합하려는 많은 새로운 ML & DL 프로젝트를보고 시작했습니다.
Vulkan SDK는 고도로 전문화 된 최적화를 가능하게하는 저수준 인터페이스를 제공하지만, 500-2000 줄의 코드가 응용 프로그램 코드를 작성하기 시작하는 비용이 많이 듭니다. 이로 인해 이러한 각 프로젝트는 Vulkan SDK의 비 계산 관련 기능을 추상화하기 위해 동일한 기준선을 구현해야했습니다. 이 많은 양의 비표준 보일러 플레이트는 지식 전달이 제한되어 있으며 고유 한 프레임 워크 구현 버그가 소개 될 가능성이 높아질 수 있습니다.
우리는 현재 Vulkan SDK 인터페이스를 숨기지 않고 (엄청나게 잘 설계되었으므로) Vulkan SDK의 GPU 컴퓨팅 기능에 직접 초점을 맞추기 위해 Kompute를 개발하고 있습니다. 이 기사는 Kompute의 동기에 대한 높은 수준의 개요와 핵심 Kompute 아키텍처뿐만 아니라 GPU 컴퓨팅을 모두 소개하는 예제에 대한 일련의 개요를 제공합니다.