Hi, I want to use the function implemented by the c language
First the overall flow is this
input --> NN --> param --> [function(C language) --> output] --> loss(output - reference)
[] is done with c.
It’s too time-consuming to implement the function implemented by c into python.
Also, the calculation of the function is specialized in c because of intel MKL.
So I tried to use ctypes to send arrays from python to c.
But in this case, I have to detach tensor and autograd.
After calculation in c language, I send arrays to python and make it be tensor type.
But when I tried to train NN, I can’t update the weight.
This is of course because the autograd is not existed.
Here comes the problem.
First, I don’t know how to make autograd of function, c part.
Second, I don’t know how to update the last of the part, the NN part without using loss.backward.
how can I do it?
here is the code
for epoch in range(num_epoch):
scheduler.step
running_loss = 0
# train
for i, (inputs, raws_in, targets, raws_out) in enumerate(train_loader):
inputs = inputs.to(device)
targets = targets.to(device)
# Polynomial model - python version
# params = model(inputs)
# inputs = torch.stack([inputs[:, 0] * inputs[:, 0], inputs[:, 0], torch.FloatTensor([1, 1, 1, 1, 1, 1]).to(device), inputs[:, 1]])
# outputs = params.matmul(inputs)
# outputs = torch.diag(outputs).view([-1, 1])
# sc3d code input - c
params = model(inputs)
grad = params.grad
print(inputs)
print(params)
print('----------------------------------------------')
params_c = params.to(torch.device('cpu'))
params_c = params_c.detach().numpy()
inputs_c = torch.stack([inputs[:, 0] * inputs[:, 0], inputs[:, 0], torch.FloatTensor([1, 1, 1, 1, 1, 1]).to(device), inputs[:, 1]])
inputs_c = inputs_c.to(torch.device('cpu'))
inputs_c = inputs_c.detach().numpy()
libname = os.path.abspath(os.path.join(os.path.dirname(__file__), "sc3d.so"))
LIBC = ctypes.CDLL(libname)
_double_pp = np.ctypeslib.ndpointer(dtype=np.uintp, ndim=1)
# _pp = np.ctypeslib.ndpointer(dtype=ctypes.c_float, ndim=1)
LIBC.polyno.argtypes = [ctypes.c_int, ctypes.c_int, _double_pp, _double_pp, _double_pp]
LIBC.polyno.restype = None
params_pp = (params_c.__array_interface__['data'][0] + np.arange(params_c.shape[0])*params_c.strides[0]).astype(np.uintp)
inputs_pp = (inputs_c.__array_interface__['data'][0] + np.arange(inputs_c.shape[0])*inputs_c.strides[0]).astype(np.uintp)
m = ctypes.c_int(params_pp.shape[0])
n = ctypes.c_int(inputs_pp.shape[0])
# outputs = np.zeros_like(m, m) # param(6*4) * input(4*6)
outputs = np.zeros((6, 1)) # param(6*4) * input(4*6)
outputs_pp = (outputs.__array_interface__['data'][0] + np.arange(outputs.shape[0])*outputs.strides[0]).astype(np.uintp)
LIBC.polyno(m, n, params_pp, inputs_pp, outputs_pp)
outputs = torch.FloatTensor(outputs).to(device)
# outputs.requires_grad_(True)
print(inputs_c)
print(params_c)
print(outputs)
print(targets)
# Forward pass
loss = criterion(outputs, targets)
# loss = torch.sqrt(criterion(outputs, targets))
# Backward and optimize
optimizer.zero_grad()
loss.backward(gradient=params.grad)
optimizer.step()
running_loss += float(losses(outputs, targets))
if (i + 1) % train_step == 0:
print('Epoch [{}/{}], Step [{}/{}], Train Loss: {}'
.format(epoch + 1, num_epoch, i + 1, train_step, running_loss/train_step), end='')
train_losses.append(running_loss / train_step)