Я пытаюсь реализовать алгоритм комбинирования, описанный в этой статье https://www.developertyrone.com/blog/generating-the-mth-lexicographical-element-of-a-mathematical-combination/ на CUDA.
, он работает для C (100,4)
n=100
k=4
, но когда япопробуйте C (200,4) Я получил сообщение об ошибке CUDA_ERROR_LAUNCH_FAILED .
n=200
k=4
Я почти уверен, что нет переполнения для вычисления комбинации n = 200, но я не мог выяснитьпричина.
Я отладил код, и переполнения не было. Одним интересным моментом является то, что код иногда запускается для C (150,4), а иногда не работает.
Я ввел все целые числа как int64. Я попытался отметить каждую строку одну за другой, чтобы найти точное положение, вызывающее ошибку. Когда кажется, что проблема с этими двумя строками в самой большой функции V
while choose(v, b) > x:
v -= 1
Когда я отметил эти две строки, она не падает.
Полный код приведен ниже:
import numba
from numba import cuda
import math
import numpy as np
from pdb import set_trace
@cuda.jit(device=True)
def choose(n, k):
if n < k:
return 0
if n == k:
return 1
delta = imax = 0
if k < n-k:
delta = n-k
imax = k
else:
delta = k
imax = n-k
ans = numba.int64(delta + 1)
for i in range(2, imax+1):
ans = numba.int64((ans * (delta + i)) / i)
return ans
@cuda.jit(device=True)
def largestV(a, b, x):
v = numba.int64(a-1)
while choose(v, b) > x:
v -= 1
return v
@cuda.jit
def cuda_calculateMth(n, k, d_result):
pos = cuda.grid(1) # pylint: disable=not-callable
if pos >= len(d_result):
return
m = numba.int64(pos)
a = numba.int64(n)
b = numba.int64(k)
x = numba.int64((choose(a, b) - 1) - m)
for i in range(k):
d_result[pos][i] = largestV(a, b, x)
x = x - choose(d_result[pos][i], b)
a = d_result[pos][i]
b -= 1
for i in range(k):
d_result[m][i] = (n-1) - d_result[m][i]
if __name__ == "__main__":
n = 200
k = 4
totalcount = int((n*(n-1)*(n-2)*(n-3)) / (4 * 3 * 2))
result = np.zeros((totalcount, 4), dtype="uint")
temp = np.zeros(10, dtype="uint")
d_result = cuda.to_device(result)
d_temp = cuda.to_device(temp)
threadsperblock = 128
blockspergrid = (totalcount +
(threadsperblock - 1)) // threadsperblock
cuda_calculateMth[blockspergrid, threadsperblock](
n, k, d_result)
result = d_result.copy_to_host()
print(result[-30:])