You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Jul 13, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Jul 13, 2026. It is now read-only.
get_global_id() indexing order doesn't follow that of SYCL indexing #889
Let's say we want to mutliply two matrices (of dimensions |a| = X*Y and |b| = Y*Z, i.e. a x b = c, |c| = X*Z) using this SYCL code:
#include<iostream>
#include<vector>
#include<string>
#include<CL/sycl.hpp>intmatmul(std::vector<int> &a,
std::vector<int> &b,
size_t row_a, size_t col_a,
size_t row_b, size_t col_b) {
size_t X = row_a, Y = col_a, Z = col_b;
std::vector<int> c(X * Z, 0);
sycl::queue queue;
std::cout << "Selected device: "
<< queue.get_device().get_info<sycl::info::device::name>()
<< "\n";
sycl::buffer Ab{a};
sycl::buffer Bb{b};
sycl::buffer Cb{c};
queue.submit([&](sycl::handler& h) {
sycl::accessor Ad{Ab,h,sycl::read_only};
sycl::accessor Bd{Bb,h,sycl::read_only};
sycl::accessor Cd{Cb,h,sycl::read_write};
sycl::range global{X, Z};
sycl::stream out(1024, 256, h);
h.parallel_for(sycl::range{global}, [=](sycl::id<2> index) {
auto i = index[0];
auto j = index[1];
out << "i = " << i << ", j = " << j << sycl::endl;
for (auto k = 0; k < Y; ++k) {
Cd[i*Z+j] += Ad[i*Y+k] * Bd[k*Z+j];
}
});
});
sycl::host_accessor Ch{Cb, sycl::read_only};
for(auto i = 0 ; i < X ; i++) {
for(auto j = 0 ; j < Z ; j++)
std::cout << Ch[i*Z+j] << "";
std::cout << std::endl;
}
return0;
}
intmain () {
std::vector<int> a(20,1);
std::vector<int> b(24,1);
matmul(a, b, 5, 4, 4, 6);
return0;
}
What we are essentially doing is parallalizing this loop:
for (auto i = 0 ; i < X ; i++)
for(auto j = 0; j < Z; j++)
for(auto k = 0 ; k < Y; k++)
c[i,j] += a[i,k] * b[k,j]
The parallel_for gets the two outer-most loop indices through get_global_id() in the kernel. Now if we print the indices, we get an expected iteration:
i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 0, j = 3
i = 0, j = 4
i = 0, j = 5
i = 1, j = 0
i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 1, j = 4
i = 1, j = 5
i = 2, j = 0
i = 2, j = 1
i = 2, j = 2
i = 2, j = 3
i = 2, j = 4
i = 2, j = 5
i = 3, j = 0
i = 3, j = 1
i = 3, j = 2
i = 3, j = 3
i = 3, j = 4
i = 3, j = 5
i = 4, j = 0
i = 4, j = 1
i = 4, j = 2
i = 4, j = 3
i = 4, j = 4
i = 4, j = 5
Now, if we look at the similar matrix multiplication code in numba_dpex:
@chudur-budur I do not understand the issue. In both SYCL and numba-dpex i, i.e., get_global_id(0) or the first index is going from [0...5) and j, i.e., get_global_id(1) goes from [0..6)].
So what is the discrepancy?
The concept of iteration order is irrelevant in this case. There is no iteration as we are not executing any loop. You are executing a data parallel kernel where X*Z work items are executing in parallel. There is some internal serialization mechanism in both dpcpp and numba-dpex to generate prints and from the look of it they differ, but that in itself proves nothing about the order in which these work items execute. In fact, by definition the order of execution of work items in a work group is undefined.
The real issue will be if you are getting different results from seemingly identical kernels written in dpcpp and dpex. Is that what you are seeing?
@chudur-budur I do not understand the issue. In both SYCL and numba-dpex i, i.e., get_global_id(0) or the first index is going from [0...5) and j, i.e., get_global_id(1) goes from [0..6)].
So what is the discrepancy?
Yea, it's not a discrepancy per se, since iteration is not related to any loop, I think we should be fine as long as indices are accessing the correct values in the array.
While there are more important sources of concern as the moment, couldn't that actually matter in the perspective of optimizing execution ? I wonder if knowing in what order the tasks will be dispatched could be leveraged to have a better cache hit rate in some kernels. In this regard I would expect tasks to be dispatched in a row-major order and could agree that this example might in fact show a concerning behavior from numba_dpex, because the SYCL kernel dispatches task in row-major order, and numba_dpex seems to show column-major order.
Activity
diptorupd commentedon Jan 29, 2023
@chudur-budur I do not understand the issue. In both SYCL and numba-dpex
i, i.e.,get_global_id(0)or the first index is going from[0...5)andj, i.e.,get_global_id(1)goes from[0..6)].So what is the discrepancy?
The concept of iteration order is irrelevant in this case. There is no iteration as we are not executing any loop. You are executing a data parallel kernel where
X*Zwork items are executing in parallel. There is some internal serialization mechanism in both dpcpp and numba-dpex to generate prints and from the look of it they differ, but that in itself proves nothing about the order in which these work items execute. In fact, by definition the order of execution of work items in a work group is undefined.The real issue will be if you are getting different results from seemingly identical kernels written in dpcpp and dpex. Is that what you are seeing?
chudur-budur commentedon Jan 30, 2023
Yea, it's not a discrepancy per se, since iteration is not related to any loop, I think we should be fine as long as indices are accessing the correct values in the array.
fcharras commentedon Jan 30, 2023
While there are more important sources of concern as the moment, couldn't that actually matter in the perspective of optimizing execution ? I wonder if knowing in what order the tasks will be dispatched could be leveraged to have a better cache hit rate in some kernels. In this regard I would expect tasks to be dispatched in a row-major order and could agree that this example might in fact show a concerning behavior from
numba_dpex, because the SYCL kernel dispatches task in row-major order, andnumba_dpexseems to show column-major order.