from bisect import bisect_left
import torch
import torch.nn.functional as F

def comparing_idx_search_methods():
    import random
    import time

    def bisect_search(nuclears, x):
        idx = bisect_left(nuclears, x)
        return idx

    def pytorch_search(nuclears, x):
        tmp_feat = 1/ (1 + F.relu(nuclears - x))
        mat_tmp = torch.max(tmp_feat, dim=1)
        return mat_tmp[1] + 1

    number_of_iterations = 1000000
    nuclears = [0, 0.1, 0.15, 0.2, 0.3, 0.33, 0.5, 0.51, 0.8, 1]

    x_s = [random.random() for _ in range(number_of_iterations)]


    start = time.time()
    for val in x_s:
        idx = bisect_search(nuclears, val)
    
    end = time.time()
    execution_time = end - start
    print("bisect: {} seconds".format(round(execution_time, 2)))

    start = time.time()
    nuclears = torch.Tensor(nuclears).view(1, -1)
    x_s_th = torch.Tensor(x_s).view(-1, 1)

    idx_th = pytorch_search(nuclears, x_s_th)

    # for val in x_s:
    #     idx = pytorch_search(nuclears, val)
    end = time.time()
    execution_time = end - start
    print("pytorch: {} seconds".format(round(execution_time, 2)))

comparing_idx_search_methods()

Just a few modifications, making it computing-parallel. Now, it surpasses normal for-loop in numpy.