Π§Π°ΡΡΠΎ Π±ΡΠ²Π°Π΅Ρ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ Π΄Π°ΡΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΡ ΡΠ΄ΡΠ° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π΅ ΠΏΠΎΡΠΎΠΊΠΎΠ² (ΡΠ°Π±ΠΎΡΠΈΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²) Π² Π±Π»ΠΎΠΊΠ΅ ΠΏΠΎΡΠΎΠΊΠΎΠ² (ΡΠ°Π±ΠΎΡΠ΅ΠΉ Π³ΡΡΠΏΠΏΠ΅). ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π°ΡΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΡ HIP Π²Π΅ΡΡ Π½ΡΡ Π³ΡΠ°Π½ΠΈΡΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΠΏΠΎΡΠΎΠΊΠΎΠ² Π² Π±Π»ΠΎΠΊΠ΅ ΠΏΠΎΡΠΎΠΊΠΎΠ² (ΡΠΊΠ°ΠΆΠ΅ΠΌ, 1024) ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ:
__launch_bounds__(1024) __global__ void fooKernel(...) { ... }
Π€Π°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ, Π΄Π»Ρ ΡΠ΅ΠΊΡΡΠ΅ΠΉ Π²Π΅ΡΡΠΈΠΈ HIP, ΠΊ ΡΠΎΠΆΠ°Π»Π΅Π½ΠΈΡ, ΡΡΠΎ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΊΠ°Π·ΡΠ²Π°ΡΡ, ΠΊΠΎΠ³Π΄Π° ΡΠ°Π·ΠΌΠ΅Ρ Π±Π»ΠΎΠΊΠ° ΠΏΠΎΡΠΎΠΊΠ° ΠΏΡΠ΅Π²ΡΡΠ°Π΅Ρ 256 (ΡΠΌ. https://github.com/ROCm-Developer-Tools/HIP/issues/1310).
CUDA ΡΠ°ΠΊΠΆΠ΅ ΠΈΠΌΠ΅Π΅Ρ ΡΠΎΡ ΠΆΠ΅ Π°ΡΡΠΈΠ±ΡΡ. Π‘ΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ ΡΠ°ΠΊΠΆΠ΅ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠΉ Π°ΡΠ³ΡΠΌΠ΅Π½Ρ Π΄Π»Ρ ΠΊΠ²Π°Π»ΠΈΡΠΈΠΊΠ°ΡΠΎΡΠ° Π³ΡΠ°Π½ΠΈΡ Π·Π°ΠΏΡΡΠΊΠ° Π΄Π»Ρ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° Π±Π»ΠΎΠΊΠΎΠ² ΠΏΠΎΡΠΎΠΊΠΎΠ² (https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#launch-bounds).
ΠΠ²Π°Π»ΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ ΡΠ΄ΡΠ° Π² OpenCL Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΡΠ»ΠΈΡΠ°ΡΡΡΡ (ΡΠΌ. 6.7.2 https://www.khronos.org/registry/OpenCL/specs/2.2/pdf/OpenCL_C.pdf)
ΠΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ v1 β Π² ΠΈΠ΄Π΅Π°Π»ΡΠ½ΠΎΠΌ ΠΌΠΈΡΠ΅, ΠΊΠΎΠ³Π΄Π° ΠΌΡ Π·Π½Π°Π΅ΠΌ ΡΠ°Π·ΠΌΠ΅Ρ Π±Π»ΠΎΠΊΠ° ΠΏΠΎΡΠΎΠΊΠ° Π²ΠΎ Π²ΡΠ΅ΠΌΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ, OCCA Π΄ΠΎΠ±Π°Π²ΠΈΡ ΠΊΠ²Π°Π»ΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ ΡΠ΄ΡΠ° Π΄Π»Ρ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΡ Π³ΡΠ°Π½ΠΈΡ Π·Π°ΠΏΡΡΠΊΠ° (CUDA, HIP) ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΡ ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ΅ ΡΠ°Π±ΠΎΡΠ΅ΠΉ Π³ΡΡΠΏΠΏΡ (OpenCL).
Proposal v2. ΠΡΠ»ΠΈ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΡΠ»ΠΎΠΆΠ½ΠΎ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ Proposal v1, Π±ΡΠ»ΠΎ Π±Ρ Π½Π΅ΠΏΠ»ΠΎΡ ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π°ΡΡΠΈΠ±ΡΡ okl Π΄Π»Ρ Π³ΡΠ°Π½ΠΈΡ Π·Π°ΠΏΡΡΠΊΠ° @qualifier("Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠ΅ ΡΠ°Π·ΠΌΠ΅ΡΡ", B), Π³Π΄Π΅ B ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΠ°. ΠΡΠΎ Π±ΡΠ΄Π΅Ρ ΡΠ°ΡΡΠΈΡΠ΅Π½ΠΎ Π΄ΠΎ __launch_bounds__(Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ B) Π΄Π»Ρ CUDA/HIP ΠΈΠ»ΠΈ __attribute__((work_group_size_hint(Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ B))) Π΄Π»Ρ OpenCL. ΠΠ½ΠΎΠ³ΠΎΠΌΠ΅ΡΠ½ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΡΠ°ΠΊΠΆΠ΅ Π±ΡΠ» Π±Ρ ΠΏΠΎΠ»Π΅Π·Π΅Π½.
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΡΠΎ ΠΏΠΎΡ ΠΎΠΆΠ΅ Π½Π° HIP/CUDA/OpenCL, ΠΊΠ°ΠΊ Π½Π°ΡΡΠ΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΅Π³ΠΎ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΡΠ²ΠΎΠΉΡΡΠ²Π° ΡΠ±ΠΎΡΠΊΠΈ?
addVectors = device.buildKernel("addVectors.okl",
"addVectors",
"launch_bounds: 1024");
ΠΡΠΎ Π±ΡΠ»ΠΎ Π±Ρ Ρ ΠΎΡΠΎΡΠΎ, Ρ Π΄ΡΠΌΠ°Ρ.
Π― ΠΏΡΠΎΡΡΠΎ ΡΡΠΎΠ»ΠΊΠ½ΡΠ»ΡΡ Ρ ΡΡΠΈΠΌ. Π― ΡΠ°Π΄ Π²Π½Π΅ΡΡΠΈ ΡΠ²ΠΎΠΉ Π²ΠΊΠ»Π°Π΄, Π½ΠΎ Ρ ΠΌΠ΅Π½Ρ Π΅ΡΡΡ Π²ΠΎΠΏΡΠΎΡ. ΠΠ½Π°Π΅Ρ Π»ΠΈ OCCA ΡΠ°Π·ΠΌΠ΅ΡΡ Π²Π½ΡΡΡΠ΅Π½Π½Π΅Π³ΠΎ ΡΠΈΠΊΠ»Π° Π²ΠΎ Π²ΡΠ΅ΠΌΡ JIT?
Π― ΡΡΠΈΡΠ°Ρ, ΡΡΠΎ ΡΠ°Π·ΠΌΠ΅ΡΡ ΡΠΈΠΊΠ»Π° ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Ρ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ² ΡΠ΄ΡΠ°.
ΠΡΠΎ ΠΏΡΠ°Π²Π΄Π°, Π½ΠΎ Ρ Π½Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ, ΠΏΠΎΡΠ΅ΠΌΡ ΡΡΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ. Π― ΡΠΏΡΠ°ΡΠΈΠ²Π°Ρ, ΠΊΠ°ΠΊ occa ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ΄Π°ΡΡ Π°ΡΡΠΈΠ±ΡΡ __launch_bounds__
Π²ΠΎ Π²ΡΠ΅ΠΌΡ JIT. Π ΡΡΠΎΠΉ ΡΠΎΡΠΊΠ΅ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ Π·Π½Π°ΡΡ ΡΠ°Π·ΠΌΠ΅ΡΡ ΠΏΠ΅ΡΠ»ΠΈ. ΠΡΠΎ ΠΎΡΡΠΎΠ³ΠΎΠ½Π°Π»ΡΠ½ΠΎ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠ°ΠΌ ΡΠ΄ΡΠ°, Π½Π΅ ΡΠ°ΠΊ Π»ΠΈ?
ΠΠ½ Π³ΠΎΠ²ΠΎΡΠΈΡ, ΡΡΠΎ ΡΠ°Π·ΠΌΠ΅ΡΡ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΡ ΡΠΈΠΊΠ»ΠΎΠ² ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Ρ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ², Ρ.Π΅. ΠΌΡ Π½Π΅ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ Π·Π½Π°Π΅ΠΌ ΡΠ°Π·ΠΌΠ΅ΡΡ Π±Π»ΠΎΠΊΠΎΠ² ΠΏΠΎΡΠΎΠΊΠΎΠ² Π²ΠΎ Π²ΡΠ΅ΠΌΡ JIT-ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ.
Π Π²Π΅ΡΠ½ΠΎ. Π― Π²ΠΈΠΆΡ, ΡΡΠΎ ΡΡ ΡΠ΅ΠΉΡΠ°Ρ Π³ΠΎΠ²ΠΎΡΠΈΡΡ @tcew. Π₯ΠΎΡΠΎΡΠ°Ρ ΡΠΎΡΠΊΠ° Π·ΡΠ΅Π½ΠΈΡ.
ΠΠΎΡ ΡΡΠΎ Ρ ΠΈΠΌΠ΅Π» Π² Π²ΠΈΠ΄Ρ:
<strong i="6">@kernel</strong> void runtimeArgs(const int B,
const int T,
const int N,
const float *x,
const float *y,
float *xPy) {
for (int b=0;b<B;++b;@outer(0)){
for (int t=0;t<T;++t;@inner(0)){
if(b==0 && t==0) printf("B=%d, T=%d\n", B, T);
int n = t + T*b;
if(n<N){
xPy[n] = x[n] + y[n];
}
}
}
}
OCCA, ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎ, Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π·Π½Π°ΡΡ ΡΠΈΡΠ»ΠΎΠ²ΡΠ΅ Π³ΡΠ°Π½ΠΈΡΡ ΡΠΈΠΊΠ»Π° Π²ΠΎ Π²ΡΠ΅ΠΌΡ JIT.
ΠΠ΄Π½Π°ΠΊΠΎ ΠΎΠ½ ΡΠΎΠ·Π΄Π°Π΅Ρ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ Π·Π°ΠΏΡΡΠΊΠ°, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ ΡΠ°Π·ΠΌΠ΅ΡΡ ΡΠ΅ΡΠΊΠΈ ΠΏΠΎΡΠΎΠΊΠΎΠ²:
extern "C" void runtimeArgs(occa::modeKernel_t * *deviceKernel,
const int & B,
const int & T,
const int & N,
occa::modeMemory_t * x,
occa::modeMemory_t * y,
occa::modeMemory_t * xPy) {
{
occa::dim outer, inner;
outer.dims = 1;
inner.dims = 1;
int b = 0;
outer[0] = B - 0;
int t = 0;
inner[0] = T - 0;
occa::kernel kernel(deviceKernel[0]);
kernel.setRunDims(outer, inner);
kernel(B, T, N, x, y, xPy);
}
}
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ, ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΌΠΎΠΆΠ΅Ρ ΡΠΊΠ°Π·Π°ΡΡ Π»ΡΠ±ΠΎΠΉ ΡΠ°Π·ΠΌΠ΅Ρ Π³ΡΠ°Π½ΠΈΡ ΡΠΈΠΊΠ»Π° Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ.
ΠΠ΅ΡΠ΅ΠΊΡΠ΅ΡΠ΅Π½Π½ΡΠ΅ ΠΏΠΎΡΡΡ.
SYCL ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ Π°Π½Π°Π»ΠΎΠ³ΠΈΡΠ½ΡΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ:
sycl::range<2> global_range(Bx*Tx,By*Ty);
sycl::range<2> local_range(Tx,Ty);
sycl::nd_range<2> kernel_range(global_range, local_range);
device_queue.submit([&](sycl::handler &cgh) {
...
cgh.parallel_for(kernel_range, kernel);
});
(ΠΡΡΠ΅ΡΡ ΠΈΠΌΠ΅ΡΡ ΡΠ²ΡΠ·Π°Π½Π½ΡΠΉ Ρ Π½ΠΈΠΌΠΈ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½, ΡΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°ΡΡ N)
Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡ SYCL sycl::range
Π°Π΄Π°ΠΏΡΠΈΡΠΎΠ²Π°Π½ ΠΈΠ· OpenCL, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ°ΠΌ Π°Π΄Π°ΠΏΡΠΈΡΠΎΠ²Π°Π½ ΠΈΠ· CUDA.
Π Π²Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ² ΠΏΠΎΡΠΎΠΊΠΎΠ² ΠΎΡΠ΄Π΅Π»Π΅Π½Π° ΠΎΡ ΡΠ΅Π»Π° ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΡΡ ΡΠΈΠΊΠ»ΠΎΠ² for.
Π‘ΠΈΠ½ΡΠ°ΠΊΡΠΈΡ OCCA OKL ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΠΎ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π½ Π΄Π»Ρ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½ΠΈΡ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ² ΡΠΈΠΊΠ»Π° ΠΈ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π° Π² Π±ΠΎΠ»Π΅Π΅ Π·Π½Π°ΠΊΠΎΠΌΡΠΉ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π° for.
for (int b=0;b<B;++b;@outer(0)){ /* grid dimension defined here */
for (int t=0;t<T;++t;@inner(0)){ /* thread block dimension defined here */
if(b==0 && t==0) printf("B=%d, T=%d\n", B, T);
int n = t + T*b;
if(n<N){
xPy[n] = x[n] + y[n];
}
}
}
ΠΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ, ΡΡΠΎ ΠΊΠΎΠ΄ Π²Π½ΡΡΡΠΈ ΡΠ΄ΡΠ° ΡΠ΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π³ΡΠ°Π½ΠΈΡΡ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π° for Π² Π½Π΅ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²Π΅Π½Π½ΠΎΠΉ Π±Π»ΠΈΠ·ΠΎΡΡΠΈ ΠΎΡ ΡΠ΅Π»Π° ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π° for. ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, Π³ΡΠ°Π½ΠΈΡΠ° ΡΠΈΠΊΠ»Π° Π½Π΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΡΡΡ ΠΊΠ°ΠΊΠΈΠΌ-Π»ΠΈΠ±ΠΎ Π²Ρ ΠΎΠ΄Π½ΡΠΌ ΠΌΠ°ΡΡΠΈΠ²ΠΎΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π±ΠΎΠ»Π΅Π΅ ΠΎΠ±ΡΠ΅Π΅ ΡΠ΄ΡΠΎ ββΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΡΡΠ΅Π±ΠΎΠ²Π°ΡΡ ΡΠΎΠ²Π΅ΡΡΠ΅Π½Π½ΠΎ Π΄ΡΡΠ³ΠΎΠΉ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΡΠ΅ΡΠΊΠΈ ΠΏΠΎΡΠΎΠΊΠΎΠ², ΡΠ΅ΠΌ ΠΌΠ°ΡΡΠΈΠ²Ρ Π΄Π°Π½Π½ΡΡ .
ΠΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ ΡΠ΄ΡΠ° OKL Π±ΡΠ»ΠΈ ΠΏΡΠ΅Π΄Π½Π°ΠΌΠ΅ΡΠ΅Π½Π½ΡΠΌ Π²ΡΠ±ΠΎΡΠΎΠΌ, Π²ΡΠ·Π²Π°Π½Π½ΡΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΡΡ Π½Π΅ΠΎΠ΄Π½ΠΎΠΊΡΠ°ΡΠ½ΠΎ ΠΎΠ±ΡΡΡΠ½ΡΡΡ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ ΡΠ΄ΡΠ° CUDA/OpenCL, ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΡΠΊΠ° ΡΠ΄ΡΠ° ΠΈ ΡΠΈΠ»ΠΎΡΠΎΡΠΈΡ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡΠΎΡΠ½ΠΎΡΡΠΈ ΡΠ΄ΡΠ° ΠΏΡΠΈ ΠΎΠ±ΡΡΠ΅Π½ΠΈΠΈ Π»ΡΠ΄Π΅ΠΉ.
ΠΡΡΡ Π»ΠΈ Π² SYCL Π°Π½Π°Π»ΠΎΠ³ΠΈΡΠ½Π°Ρ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΠ° ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΠ΅ Π±Π»ΠΎΠΊΠ° ΠΏΠΎΡΠΎΠΊΠ°, ΠΊΠ°ΠΊ __launch_bounds__
Π² CUDA/HIP, ΠΊΠΎΡΠΎΡΡΡ ΠΌΡ Π·Π΄Π΅ΡΡ ΠΎΠ±ΡΡΠΆΠ΄Π°Π΅ΠΌ?
Π₯ΠΎΡΠΎΡΠΈΠΉ Π²ΠΎΠΏΡΠΎΡ. Π― Π΄Π²Π°ΠΆΠ΄Ρ ΠΏΡΠΎΠ²Π΅ΡΠΈΠ» ΡΡΠ°Π½Π΄Π°ΡΡ SYCL (v1.2.1), ΡΡΠΎΠ±Ρ Π²ΡΡΡΠ½ΠΈΡΡ ΡΡΠΎ. ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡΡΡ Π»ΡΠ±ΡΠ΅ Π°ΡΡΠΈΠ±ΡΡΡ, Π΄ΠΎΡΡΡΠΏΠ½ΡΠ΅ Π² OpenCL C, ΠΈ ΠΈΡ
ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°ΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠ° Π°ΡΡΠΈΠ±ΡΡΠ° C++ 11 Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π° ΠΈΠΌΠ΅Π½ cl
. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, __attribute__(((reqd_work_group_size(n)))
Π² OpenCL C ΡΠΊΠ²ΠΈΠ²Π°Π»Π΅Π½ΡΠ½ΠΎ [[cl::reqd_work_group_size(n)]]
Π² SYCL.
Π‘ΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ Π΄Π²Π° Π²Π°ΡΠΈΠ°Π½ΡΠ° ΡΠΊΠ°Π·Π°Π½ΠΈΡ ΡΠ°Π·ΠΌΠ΅ΡΠ° Π³ΡΡΠΏΠΏΡ ΠΏΠΎΡΠΎΠΊΠΎΠ²: work_group_size_hint(n)
β ΡΡΠΎ ΠΌΡΠ³ΠΊΠ°Ρ Π²Π΅ΡΡΠΈΡ, ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°ΡΡΠ°Ρ, ΡΡΠΎ ΡΠ°Π·ΠΌΠ΅Ρ Π³ΡΡΠΏΠΏΡ ΠΏΠΎΡΠΎΠΊΠΎΠ² Π±ΡΠ΄Π΅Ρ n
, ΡΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ req_work_group_size(n)
ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΡΡΠΎΠ³ΠΈΠΌ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ. .
ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΡ OCCA:
Π΄ΠΎΠ±Π°Π²ΡΡΠ΅ ΡΡΠ½ΠΊΡΠΈΡ-ΡΠ»Π΅Π½ "innerDimHint" Π² ΠΊΠ»Π°ΡΡ occa::kernel, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΡΠ·ΡΠ²Π°Π΅Ρ ΠΏΠ΅ΡΠ΅ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ (Π΅ΡΠ»ΠΈ ΠΎΠ½Π° Π΅ΡΠ΅ Π½Π΅ Π² Ρ ΡΡΠ΅) Ρ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΠΎΠΉ ΠΏΠΎΡΠΎΠΊΠ° Π΄Π»Ρ CUDA/OpenCL/HIP.
Π΄ΠΎΠ±Π°Π²ΡΡΠ΅ Π½Π΅ΠΊΠΎΡΠΎΡΡΡ Π»ΠΎΠ³ΠΈΠΊΡ Π²Π½ΡΡΡΠΈ ΡΡΠ΅Π΄ΡΡΠ²Π° Π·Π°ΠΏΡΡΠΊΠ°, ΡΡΠΎΠ±Ρ Π²ΡΠ·Π²Π°ΡΡ ΠΏΠ΅ΡΠ΅ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ, ΠΊΠΎΠ³Π΄Π° ΡΠΊΠ°Π·Π°Π½ Π½ΠΎΠ²ΡΠΉ ΡΠ°Π·ΠΌΠ΅Ρ ΠΌΠ°ΡΡΠΈΠ²Π° ΠΏΠΎΡΠΎΠΊΠΎΠ². ΠΡΠ° ΡΡΠ½ΠΊΡΠΈΡ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π²ΠΊΠ»ΡΡΠ΅Π½Π°/Π²ΡΠΊΠ»ΡΡΠ΅Π½Π° Π½Π΅ΠΊΠΎΡΠΎΡΡΠΌΠΈ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡΠΌΠΈ OCCA_ * .
ΠΠ±Π° ΠΎΠ½ΠΈ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΡΠΌ ΡΠΏΠΎΡΠΎΠ±ΠΎΠΌ.
ΠΠ° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅ Ρ Π±Ρ Π΄ΠΎΠ²Π΅ΡΠΈΠ» ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΡΡΠΈΠΌ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΌ ΡΡΠ΅Π΄Π°ΠΌ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΈ ΠΏΡΠ΅Π΄ΠΏΠΎΡΠ΅Π» Π±Ρ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ ΠΏΠ΅ΡΠ΅ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡΠΎΠ²Π°ΡΡ. ΠΠΎ ΡΡΡΠΈ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΠΎΠ΅ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ @ dmed256 ΡΠ΄Π΅Π»Π°ΡΡ Π΅Π³ΠΎ ΠΎΠΏΠΎΡΠΎΠΉ ΡΠ±ΠΎΡΠΊΠΈ, Π° Π·Π°ΡΠ΅ΠΌ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΡΡ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΡ __launch_bound__
Π² ΡΠ΄ΡΠΎ ββββΠΏΡΠΈ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄Π΅, Π΅ΡΠ»ΠΈ ΡΠ΅ΡΠ²Π΅ΡΠ½Π°Ρ ΡΠ°ΡΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ ΡΡΠΎ.
ΠΠ»Ρ CUDA ΠΈ HIP __launch_bound__
Π½Π° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅ ΠΏΡΠΎΡΡΠΎ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΠ°, ΠΏΠΎΡΡΠΎΠΌΡ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π±ΠΎΠ»ΡΡΠ΅ ΠΏΠΎΡ
ΠΎΠΆΠ΅ Π½Π° work_group_size_hint
Π² OpenCL. ΠΠ½ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΡΠΎΠΎΠ±ΡΠΈΡΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΡ, ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ΅Π³ΠΈΡΡΡΠΎΠ², ΠΏΠΎ Π΅Π³ΠΎ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, Π±ΡΠ΄Π΅Ρ Π΄ΠΎΡΡΡΠΏΠ½ΠΎ ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡ ΠΏΠΎΡΠΎΠΊΡ Π² Π±Π»ΠΎΠΊΠ΅. ΠΡΠ»ΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π½Π°ΡΡΡΠ°Π΅Ρ Π³ΡΠ°Π½ΠΈΡΡ Π·Π°ΠΏΡΡΠΊΠ°, ΡΡΠΎ Π½Π΅ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ ΠΎΡΠΈΠ±ΠΊΠ°, ΡΠ°ΠΊ ΠΊΠ°ΠΊ ΡΠ΄ΡΠΎ ββΠΌΠΎΠΆΠ΅Ρ Π½Π΅ Π°ΠΊΡΠΈΠ²Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ. Π ΡΠ»ΡΡΠ°Π΅, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Π½Π°ΡΡΡΠ°Π΅Ρ Π³ΡΠ°Π½ΠΈΡΡ Π·Π°ΠΏΡΡΠΊΠ° ΠΈ ΡΠ΅Π³ΠΈΡΡΡΠ° Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ, ΡΡΠ΅Π΄Π° Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π²ΡΠ΄Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΡ, ΠΊΠΎΡΠΎΡΡΡ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡΠ»ΠΎΠ²ΠΈΡΡ OCCA.
ΠΡΠΈ Π·Π°ΠΏΡΡΠΊΠ΅ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΡΡΠ½Π΅ΡΠ° Ρ Π·Π°ΠΌΠ΅ΡΠΈΠ» ΠΎΡΠΈΠ±ΠΊΠΈ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ Π΄Π»Ρ ΡΠ΄Π΅Ρ OCCA:HIP , ΠΊΠΎΡΠΎΡΡΠ΅ ΡΡΠ΅Π±ΠΎΠ²Π°Π»ΠΈ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΠΌΠ½ΠΎΠ³ΠΎ LDS ΠΈΠ»ΠΈ REG. Π― ΡΠΊΠ΅ΠΏΡΠΈΡΠ΅ΡΠΊΠΈ ΠΎΡΠ½ΠΎΡΠΈΠ»ΡΡ ΠΊ ΡΠΎΠΌΡ, ΡΡΠΎ HIP Π±ΡΠ΄Π΅Ρ Π²ΡΠ΄Π°Π²Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π±ΡΠ΄ΡΡ ΠΎΠ±Π½Π°ΡΡΠΆΠ΅Π½Ρ. ΠΠ°Π΄Π΅ΡΡΡ, ΡΠ΅ΠΏΠ΅ΡΡ ΡΡΠΎ ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½ΠΎ.
ΠΠ΅Π½Ρ ΡΡΡΡΠ°ΠΈΠ²Π°Π΅Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠ°Ρ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΠ° ΠΈΠ»ΠΈ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ Π·Π°ΠΏΡΡΠΊΠ°, ΠΊΠΎΡΠΎΡΠΎΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ Π½ΠΎΠ²ΡΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΏΠΎΡΠΎΠΊΠΎΠ² Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ.
Π Π²Π°ΡΠ΅ΠΌΡ ΡΠ²Π΅Π΄Π΅Π½ΠΈΡ, Ρ Π±ΡΠ» ΡΡΠ°ΡΡΠ»ΠΈΠ² ΠΊΠ°ΠΊ ΡΡΡΠΊΠ°, ΠΏΡΠΎΡΡΠΎ ΡΠΊΠ°Π·Π°Π² ΡΠ²Π½ΡΠ΅ Π³ΡΠ°Π½ΠΈΡΡ ΡΠΈΠΊΠ»Π° Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΈΠ· ΠΊΠΎΠ΄Π° Ρ
ΠΎΡΡΠ° Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΏΠΎΠ΄ΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ ΠΌΠ°ΠΊΡΠΎΠΊΠΎΠ½ΡΡΠ°Π½Ρ Π² ΠΊΠΎΠ΄Π΅ ΡΠ΄ΡΠ° OKL (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, K_blockDim
Π΄Π»Ρ Π²Π½Π΅ΡΠ½Π΅Π³ΠΎ, K_threadDim
Π΄Π»Ρ Π²Π½ΡΡΡΠ΅Π½Π½Π΅Π³ΠΎ), ΠΊΠΎΡΠΎΡΡΠ΅ Ρ ΠΏΠ΅ΡΠ΅Π΄Π°Ρ Π²Π½ΠΈΠ· ΡΠ΅ΡΠ΅Π· ΡΠ΅ΠΊΠ²ΠΈΠ·ΠΈΡΡ ΡΠ΄ΡΠ°. ΠΠΎΠ½Π΅ΡΠ½ΠΎ, Ρ ΠΌΠ΅Π½Ρ Π΅ΡΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΉ ΠΊΠΎΠ΄ API, ΠΊΠΎΡΠΎΡΡΠΉ Π·Π°ΠΏΡΠ°ΡΠΈΠ²Π°Π΅Ρ Ρ
Π°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊΠΈ ΠΈ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ GPU. Π― ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΡΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π΄Π»Ρ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ Π³ΡΠ°Π½ΠΈΡ ΡΠΈΠΊΠ»Π° Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π²Π½ΠΈΠ·. ΠΠ°, ΡΠ°ΠΊΠΈΠ΅ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈΠ΅ Π²Π΅ΡΠΈ ΠΈΠ½ΠΎΠ³Π΄Π° Π²ΡΠ·ΡΠ²Π°ΡΡ ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ JIT Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ, Π½ΠΎ Π² ΠΌΠΎΠ΅ΠΌ ΡΠ»ΡΡΠ°Π΅ ΡΡΠΎ ΡΠ΅Π΄ΠΊΠΎ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Ρ ΠΈΠ·ΠΌΠ΅Π½ΡΡ ΠΏΠΎΡΠΎΠ³ΠΎΠ²ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΡΠ°Π³Π°, ΠΏΠΎΡΡΠΎΠΌΡ ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ Π³ΡΠ°Π½ΠΈΡΡ ΡΠΈΠΊΠ»Π° ΠΎΠ±ΡΡΠ½ΠΎ ΠΎΡΡΠ°ΡΡΡΡ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½ΡΠΌΠΈ ΠΈΠ»ΠΈ ΠΏΠΎΠΏΠ°Π΄Π°ΡΡ Π² ΠΊΠ°ΠΊΠΎΠΉ-ΡΠΎ ΠΎΠ±ΡΠΈΠΉ Π½Π°Π±ΠΎΡ Π΄Π»Ρ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΡΠ΄ΡΠ°. Π― ΡΠ°ΠΊΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΡΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ Π΄Π»Ρ Π½Π΅ΠΊΠΎΡΠΎΡΡΡ
ΡΠ²ΠΎΠΈΡ
ΡΠ΄Π΅Ρ, ΡΡΠΎ ΡΠ°ΠΊΠΆΠ΅ ΡΠΌΠ΅Π½ΡΡΠ°Π΅Ρ ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΡ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ JIT.
Π―Π²Π½ΠΎΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΡΡΠΈΡ Π³ΡΠ°Π½ΠΈΡ ΡΠΈΠΊΠ»Π° Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΡΠ°ΠΊΠΆΠ΅ ΠΎΠ±Π»Π΅Π³ΡΠ°Π΅Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΡΠ°Π·ΠΌΠ΅ΡΠ° ΠΌΠ°ΡΡΠΈΠ²ΠΎΠ² Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎΠΉ ΠΏΠ°ΠΌΡΡΠΈ Π³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΡΠΎΡΠ΅ΡΡΠΎΡΠ° Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Ρ ΠΈΡ ΠΏΠΎΠΌΠΎΡΡΡ Π² ΠΊΠΎΠ΄Π΅ OKL.
ΠΠΎΡ
ΠΎΠΆΠ΅, ΡΡΠ° ΡΡΠ½ΠΊΡΠΈΡ Π±ΡΠ΄Π΅Ρ Π²Π°ΠΆΠ½Π°:
https://rocmdocs.amd.com/en/latest/Current_Release_Notes/Current-Release-Notes.html#performance-impact-for-kernel-launch-bound-attribute
ΠΡΠΈΠ½ΠΎΡΡ ΠΈΠ·Π²ΠΈΠ½Π΅Π½ΠΈΡ Π·Π° Π½Π΅ΡΠΊΠ»ΡΠΆΡΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ, ΡΡΠΎ ΠΎΠ±Ρ ΠΎΠ΄Π½ΠΎΠΉ ΠΏΡΡΡ, ΠΊΠΎΡΠΎΡΡΠΉ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ Π΄Π»Ρ ΡΠ΄ΡΠ° Π² libparanumal, Π΄Π»Ρ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ Np (> 256) ΠΏΠΎΡΠΎΠΊΠΎΠ²:
occa::properties kernelInfo;
...
if(platform.device.mode()=="HIP"){
char newflag[BUFSIZ];
sprintf(newflag, " --gpu-max-threads-per-block=%d", mesh.Np);
kernelInfo["compiler_flags"] += newflag;
}
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ»Π°Π³Π° ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΎΡΠ° hipcc Π΄Π»Ρ ΡΠΊΠ°Π·Π°Π½ΠΈΡ Π³ΡΠ°Π½ΠΈΡ Π·Π°ΠΏΡΡΠΊΠ° Π±ΡΠ»ΠΎ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΎ ΠΠΎΡΠ»Π΅ΠΌ Π§Π°Π»ΠΌΠ΅ΡΡΠΎΠΌ. ΠΡΡΠ±Π°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΌΠΎΡ.
ΠΡΠΈ ΡΡΠΎΠΌ Π²Π°ΠΆΠ½ΠΎ ΡΠΎΠ±Π»ΡΠ΄Π°ΡΡ ΠΎΡΡΠΎΡΠΎΠΆΠ½ΠΎΡΡΡ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π½Π΅ΡΡΠ½ΠΎ, ΡΡΠΎ ΠΏΡΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ, Π΅ΡΠ»ΠΈ ΡΠ΄ΡΠΎ ββΠ½Π°ΡΡΡΠΈΡ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΡΡ Π³ΡΠ°Π½ΠΈΡΡ.
Π§ΡΠΎΠ±Ρ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π½Π΅ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ΡΡΠΈΡ
ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠΉ, Ρ ΡΠΎΠ·Π΄Π°Ρ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ ΠΊΠΎΠΏΠΈΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ° occa::properties
Π΄Π»Ρ ΡΠ΄Π΅Ρ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΠΈΡ
Π΄ΡΡΠ³ΠΎΠ΅ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΡΠΎΠΊΠΎΠ².
ΠΠΏΠΎΠ»Π½Π΅ Π²Π΅ΡΠΎΡΡΠ½ΠΎ, ΡΡΠΎ Π² Π±ΡΠ΄ΡΡΠ΅ΠΌ Π½Π°ΡΡΡΠ΅Π½ΠΈΠ΅ Π³ΡΠ°Π½ΠΈΡ Π·Π°ΠΏΡΡΠΊΠ° ΡΡΠ°Π½Π΅Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ.