Сбой кода Numba CUDA из-за неизвестной ошибки, исправлено добавлением пустого оператора печати в любом потоке.Python

Программы на Python
Ответить
Anonymous
 Сбой кода Numba CUDA из-за неизвестной ошибки, исправлено добавлением пустого оператора печати в любом потоке.

Сообщение Anonymous »

Я пишу код гамильтоновой эволюции, который в значительной степени основан на умножении матриц, поэтому я пытался узнать о разработке для графического процессора с использованием Python.
Однако, когда я запускаю эти строки кода внутри моей функции-оболочки временной эволюции:

Код: Выделить всё

momentum_update_kernel[blocks, threads_per_block](config, dt / 2, staple_gpu, Barray_gpu, V2Barray_gpu, g_in)
cuda.synchronize()
print("momentum updated")
link_update_kernel[blocks, threads_per_block](config, dt, lie_gens)
Я начал получать «ошибку 700» в строке cuda.synchronize().
При попытке отладить это с помощью операторов печати я заметил, что код начал успешно компилироваться, а также давать правдоподобные ответы, что позволяет мне предположить, что он работает правильно, когда в код добавляется оператор печати. Это наводит меня на мысль, что существует какая-то проблема с синхронизацией потоков, и скомпилированная версия с оператором печати каким-то образом позволяет избежать этого. Код momentum_update выглядит следующим образом:

Код: Выделить всё

def momentum_update(config, dt, staple_index_array, Barray, V2Barray, idx, out, g):

links = config[0]
momentum = config[1]
inshape = links.shape

numnodes = inshape[0]
numdims = inshape[1]

total_matricies = numnodes * numdims

if idx >= total_matricies:
return

nodeindex = idx // numdims
direction = idx % numdims

if idx == 0:
print("") #there for debug reasons, not entirely sure what's happening here

#making the staple

temp = cuda.local.array((2, 2), dtype=complex128)
temp2 = cuda.local.array((2, 2), dtype=complex128)
Vdirection = cuda.local.array((2,2), dtype=complex128)

Vdirection[0,0] = 0
Vdirection[0, 1] = 0
Vdirection[1, 0] = 0
Vdirection[1, 1] = 0

for i in range(numdims):
idx_tuple_1 = staple_index_array[nodeindex, direction,i, 0, 0]
idx_tuple_2 = staple_index_array[nodeindex, direction, i, 0, 1]
idx_tuple_3 = staple_index_array[nodeindex, direction, i, 0, 2]
idx_tuple_4 = staple_index_array[nodeindex, direction, i, 1, 0]
idx_tuple_5 = staple_index_array[nodeindex, direction, i, 1, 1]
idx_tuple_6 = staple_index_array[nodeindex, direction, i, 1, 2]

staple_matrix_1 = links[idx_tuple_1[0], idx_tuple_1[1]]
staple_matrix_2 = links[idx_tuple_2[0], idx_tuple_2[1]]
staple_matrix_3 = links[idx_tuple_3[0], idx_tuple_3[1]]

staple_matrix_4 = links[idx_tuple_4[0], idx_tuple_4[1]]
staple_matrix_5 = links[idx_tuple_5[0], idx_tuple_5[1]]
staple_matrix_6 = links[idx_tuple_6[0], idx_tuple_6[1]]

Bval = Barray[nodeindex, direction, i]
V2Bval = V2Barray[nodeindex, direction, i]

#calculating first staple
dagger_2x2_cuda(staple_matrix_2, temp)

matmul_2x2_cuda(staple_matrix_1, temp, temp2)

dagger_2x2_cuda(staple_matrix_3, temp)

matmul_2x2_cuda(temp2, temp, temp2)

scale_2x2_cuda(temp2, Bval, temp2)
add_2x2_cuda(temp2, Vdirection, Vdirection)

# calculating second staple
dagger_2x2_cuda(staple_matrix_4, temp)
dagger_2x2_cuda(staple_matrix_5, temp2)
matmul_2x2_cuda(temp, temp2, temp2)
matmul_2x2_cuda(temp2, staple_matrix_6, temp2)
scale_2x2_cuda(temp2, V2Bval, temp2)
add_2x2_cuda(temp2, Vdirection, Vdirection)

#calculating staple contribution
matmul_2x2_cuda(links[nodeindex, direction], Vdirection, temp)

dagger_2x2_cuda(temp, temp2)

scale_2x2_cuda(temp, -1, temp)
add_2x2_cuda(temp2, temp, temp)

scale_2x2_cuda(temp, 1/g**2, temp)
scale_2x2_cuda(temp, dt, temp)

#calculating new momentum
add_2x2_cuda(momentum[nodeindex, direction], temp, temp2)
for i in range(2):
for j in range(2):
config[1][nodeindex, direction,i,j] = temp2[i,j]

Фактический код momentum_update_kernel не представляет особого интереса и, по сути, просто определяет idx и вызывает momentum_update, поэтому я не включил его сюда.
Теперь одной из возможных проблем является своего рода состояние гонки, поскольку momentum_update одновременно читает и записывает конфигурацию. Однако я подозреваю, что это не так. config — это массив (2, N, d, 2, 2), и каждый поток при обновлении импульса должен читать только из:
  • массива ссылок, массива (N, d, 2, 2), хранящегося в config[0], и
  • конкретного значения импульса, которое он обновляет.
Таким образом, несколько потоков могут читать из одной и той же памяти. сразу, но ничего не должно читаться из чего-то, куда записывает другой поток.
Когда я масштабирую размер моделирования до размера, с которым я действительно хочу его запустить, он начинает давать сбой независимо от присутствия оператора печати, поэтому я не могу просто оставить оператор печати в качестве хакерского исправления.
Есть ли хотя бы способ отладить это? Очевидно, что momentum_update вызывает несколько других функций, но если бы это была какая-то ошибка с другими функциями, я бы ожидал, что гамильтонова эволюция начнет давать мне неверные ответы (раньше у меня были ошибки, скажем, в matmul_2x2_cuda, из-за которых он не работал должным образом, когда выходной массив был таким же, как один из входных данных, но я мог это сказать, потому что внезапно моделирование стало численно нестабильным), чего, похоже, не происходит.
Я запускаю это на GTX1060 в моем настольном компьютере, но ошибка также присутствует, скажем, на узлах графического процессора ComputeCanada (и на самом деле хак оператора печати там не работает).

Подробнее здесь: https://stackoverflow.com/questions/798 ... n-of-blank
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»