2014-01-19 14 views
0

我在寻找一些关于Miller-Rabin素数证明的并行实现的建议。我们假设在输入端有一些大的奇数nm参数,这意味着它应该向前搜索多少个奇数(所以它就像n,n+2,n+4等等)。我想发动内核:__syncthreads的常见每块指令

miller_rabin_kernel<<<m, k>>>(dev_n, ..) 

其中k是另一个启动参数,例如它设置为20,但它可能会更大。对于每个线程都有一些特定的数学计算,但也有一些常见的指令(即“块范围”),并且必须在这些“线程范围”之前执行。据我所知,可以使用__syncthreads设置同步屏障,因此块中的每个线程必须等到所有完成。我对这种结构的想法是这样的:

__global__ void miller_rabin_kernel(..) { 
    if (threadIdx.x == 0) { 
     // Calculate t, s, that are common for all threads in current block 
    } 
    __syncthreads(); 

    // Perform further calculations with use of t and s 
} 

是否有一些更好的方法,或者它是相当普遍的做法?

+0

你的方法是合理的。如果每个块的变量t,s等不同,那么你的方法是有道理的。如果t,s等对于所有块都是相同的,那么预先计算并将它们作为内核参数传递,或者使用模板化内核可能会更好。 –

+0

是的,这些t,s变量对于每个块是不同的,因为它们取决于n + 2 * blockIdx.x值。说实话,他们可以在主机端的某个预处理阶段为每个编号提前做好准备,并将其转换为设备内存,但是我想将大多数操作转换为并行代码。诀窍是我实际上有**两级并行化。 –

+0

具有两级并行性,动态并行会有帮助吗? – JackOLantern

回答

1

你的例子是一个合理的方法,当有特定的数量需要计算,每块不同。

如果你有大量的块,并计算为ts是相当激烈的,那么你可能由具有独立内核预计算你ts值达到一定的益处,使用每数量一个线程,但是因此能够有效地使用块中的所有线程。由于所有线程都参与,此内核可以更有效地使用设备计算能力和内存带宽。然后,您可以留下您的ts数量在全球数组,你会每块访问:

t = t_array[blockIdx.x]; 

后您的ts安装内核完成之后,你可以再打电话约你表现出你的主要内核。

调用第一个内核会有一些开销,可能只有几微秒。同样,如果ts的计算是激烈的,提高的效率可能会抵消可能的收益的开销。

+0

辉煌,非常感谢:) –