Vì vậy, tôi đã chơi xung quanh với OpenCL một chút ngay bây giờ và kiểm tra tốc độ truyền bộ nhớ giữa máy chủ và thiết bị. Tôi đang sử dụng SDK Intel OpenCL và chạy trên Intel i5 Processor với đồ họa tích hợp. Sau đó tôi phát hiện ra clEnqueueMapBuffer
thay vì clEnqueueWriteBuffer
mà hóa ra là nhanh hơn gần 10 lần khi sử dụng bộ nhớ gắn như vậy:CL_MEM_ALLOC_HOST_PTR chậm hơn CL_MEM_USE_HOST_PTR
int amt = 16*1024*1024;
...
k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, a, NULL);
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, b, NULL);
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, ret, NULL);
int* map_a = (int*) clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_b = (int*) clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_c = (int*) clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
clFinish(c_q);
đâu a
b
và ret
là 128 bit liên kết int mảng. Hiện ra khoảng 22,026186 ms, so với 198,604528 ms sử dụng clEnqueueWriteBuffer
Tuy nhiên, khi tôi đã thay đổi mã của tôi để
k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
int* map_a = (int*)clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_b = (int*)clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_c = (int*)clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
/** initiate map_a and map_b **/
thời gian tăng lên 91,350065 ms
Điều gì có thể là vấn đề? Hay nó là một vấn đề?
EDIT: Đây là cách tôi khởi tạo các mảng trong mã thứ hai:
for (int i = 0; i < amt; i++)
{
map_a[i] = i;
map_b[i] = i;
}
Và bây giờ mà tôi kiểm tra, map_a và map_b làm chứa các yếu tố ngay ở phần cuối của chương trình, nhưng map_c chứa tất cả 0. Tôi đã làm điều này:
clEnqueueUnmapMemObject(c_q, k_a, map_a, 0, NULL, NULL);
clEnqueueUnmapMemObject(c_q, k_b, map_b, 0, NULL, NULL);
clEnqueueUnmapMemObject(c_q, k_c, map_c, 0, NULL, NULL);
và hạt nhân của tôi chỉ là
__kernel void test(__global int* a, __global int* b, __global int* c)
{
int i = get_global_id(0);
c[i] = a[i] + b[i];
}
trong mã thứ hai, bạn có thể cho biết cách bạn khởi tạo k_a, k_b và k_c với dữ liệu a, b và ret và vị trí clFinish. Nếu 2 mã làm những việc khác nhau sẽ rất khó để giúp bạn –
Xin lỗi, mã giống nhau tôi không sao chép mọi thứ một cách vô tình.Trong mã thứ hai, tôi không khởi tạo k_c với ret vì tôi nghĩ rằng tôi có thể đọc dữ liệu từ map_c. – selena731
Sau khi ánh xạ và sử dụng, bạn có thể để unmap, hoặc để thực hiện một clWrite/Read từ đối tượng được ánh xạ để đảm bảo tính nhất quán của bộ nhớ. – DarkZeros