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)