2017-03-02 77 views
0

我想對如何創建在多個設備上運行的openCL測試有疑問 假設我想創建一個openCL程序來計算表達式A B + C d,這是我的意見如何創建在多個設備上運行的openCL測試

  1. 創建3個內核,一個用於B,一個用於C d,以及其他爲M + N(A B + C d)
  2. 創建一個主機代碼,並行執行3個任務,每個任務在不同的設備上運行,但我不知道如何指定特定的設備單個任務

請幫我 謝謝

+0

你停在哪裏?您是否選擇了平臺和設備,然後選擇隊列但不能將任務分配給這些設備? –

+0

哪個版本的opencl?什麼樣的設備?什麼樣的工作分配? –

回答

2

OpenCL是,所有的事情考慮,一個相當明確的API。它要求您在創建上下文時指定特定的設備,並要求您在創建隊列時指定特定的上下文。因此,在最字面意義,完成你的任務就是爲

//This is going to be pseudocode; I'm not going to look up the literal syntax for this stuff 
//It is going to closely resemble how you'd write this code in C++, though 
std::vector<_type> perform_tasks(cl_device_id ab_device, cl_device_id cd_device, cl_device_id n_m_device) { 
    cl_context ab_context = clCreateContext(ab_device); 
    cl_context cd_context = clCreateContext(cd_device); 
    cl_context n_m_context = clCreateContext(n_m_device); 
    cl_command_queue ab_queue = clCreateQueue(ab_context, ab_device); 
    cl_command_queue cd_queue = clCreateQueue(cd_context, cd_device); 
    cl_command_queue n_m_queue = clCreateQueue(n_m_context, n_m_device); 
    cl_kernel ab_kernel = get_ab_kernel(ab_context, ab_device); 
    cl_kernel cd_kernel = get_ab_kernel(cd_context, cd_device); 
    cl_kernel n_m_kernel = get_ab_kernel(n_m_context, n_m_device); 
    set_args_for_ab(ab_kernel); 
    set_args_for_cd(cd_kernel); 
    set_args_for_n_m(n_m_kernel); 
    cl_event events[2]; 
    clEnqueueKernel(ab_queue, ab_kernel, &events[0]); 
    clEnqueueKernel(cd_queue, cd_kernel, &events[1]); 
    //Here, I'm assuming that the n_m kernel depends on the results of ab and cd, and thus 
    //must be sequenced afterwards. 
    clWaitForEvents(2, events); 
    copy_ab_and_cd_data_into_n_m_buffers(); 
    cl_event n_m_event; 
    clEnqueueKernel(n_m_queue, n_m_kernel, &n_m_event); 
    clWaitForEvents(1, &n_m_event); 
    return copy_n_m_data_to_host(); 
} 

簡單但有一個更大的問題需要解決,這似乎已經通過你的問題未被考慮的:爲什麼呢?

您希望從這種邏輯中獲得什麼樣的性能提升,而不是簡單地在單個設備上執行如下所示的操作?

kernel void ab_cd(global _type * a, global _type * b, global _type * c, global _type * d, global _type * output) { 
    long id = get_global_id(0); 
    output[id] = a[id] * b[id] + c[id] * d[id]; 
} 

用那種你提出的程序邏輯的,你會從無非是想轉移不同的設備(這在我所描述的僞代碼裏面copy_ab_and_cd_data_into_n_m_buffers()發生)之間的數據招致不可避免的開銷。如果你正在致力於使用這種程序的多個設備,它仍然是簡單的(也可能是更好的性能!)寫的是這樣的:

//Again; using pseudocode. Again, gonna look like C++ code. 
cl_event perform_tasks(cl_device_id device, cl_context * context, cl_command_queue * queue, cl_kernel * kernel) { 
    *context = clCreateContext(device); 
    *queue = clCreateQueue(context, device); 
    *kernel = get_kernel(); 
    cl_event event; 
    clEnqueueKernel(queue, kernel, &event); 
    return event; 
} 

int main() { 
    std::vector<cl_device_id> device_ids = get_device_ids(); 
    std::vector<_type> results; 
    std::vector<cl_context> contexts(device_ids.size()); 
    std::vector<cl_command_queue> queues(device_ids.size()); 
    std::vector<cl_kernel> kernels(device_ids.size()); 
    std::vector<cl_event> events; 
    for(size_t i = 0; i < device_ids.size(); i++) { 
     events.emplace_back(perform_tasks(device_ids[i], &contexts[i], &queues[i], &kernels[i])); 
    } 
    clWaitForEvents(events.size(), events.data()); 
    for(cl_command_queue const& queue : queues) { 
     std::vector<_type> result = read_results_from_queue(queue); 
     results.insert(results.end(), result.begin(), result.end()); 
    } 
    //results now contains the results of all executions 
    return 0; 
} 

除非你用FPGA的工作,或處理一個特別是異乎尋常的工作量,在這種情況下,讓不同的設備完成不同的工作是絕對必要的,你可能只是爲自己創造更多的工作,而不是你需要的。

+0

謝謝Xirema,我正在開發一個運行在多個FPGA器件上的openCL測試,所以它真的讓我頭痛不已 – tpham1002002

+0

@ tpham1002002等等,你真的*都是*處理FPGA的?呵呵。那麼,正如我所提到的,我提供的第一個代碼將處理該模型。請記住,儘管我的原始聲明仍然適用:但有很少的情況下,將多個設備之間的單個計算拆分是有意義的,特別是如果該計算的子組件在設備之間相似。 – Xirema

相關問題