Skip to content

Instantly share code, notes, and snippets.

@amartya18x
Last active June 7, 2018 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amartya18x/28c3eb331cafdbffa258548b55a5e0f8 to your computer and use it in GitHub Desktop.
Save amartya18x/28c3eb331cafdbffa258548b55a5e0f8 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Instructions\n",
"\n",
"* Install SHEEP (https://github.com/alan-turing-institute/SHEEP) \n",
"```\n",
" Follow Instructions on README\n",
"```\n",
"* Install matSHEEP (https://pypi.org/project/matSHEEP/)\n",
"```\n",
" pip install matSHEEP\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from matSHEEP import enc_vec, enc_mat, enc_tensor3\n",
"from matSHEEP import functions\n",
"from matSHEEP import utils\n",
"from matSHEEP.circuit import circuit\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Reduce Addition Check"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"nb = 8\n",
"depth = int(math.floor(math.log(nb, 2)))\n",
"samples=2\n",
"inp = enc_vec(name='in', nb=nb)\n",
"out = enc_vec(name='out', nb=depth+1)\n",
"ra = functions.reduce_add('adder', inp, out)\n",
"ra_obj = circuit('reduce_add', ra)\n",
"ra_obj.write_file(filename='./test.sheep')\n",
"processing_time = np.zeros(samples)\n",
"for idx in range(0, samples):\n",
" inp_arr_val = list(map(lambda x : int(x), np.random.uniform(size=nb)> 0.5))\n",
" inp_file = inp.get_input_dict(inp_arr_val, write_file=True)\n",
" results = ra_obj.run_circuit(inp_file)\n",
" processing_time[idx] = results['Processing times (s)']['circuit_evaluation']\n",
" out_vars = out.get_variables()\n",
" err_str = str(''.join(results['Outputs'][var] for var in out_vars)[::-1]) +\" -- \"+ str(np.asarray(inp_arr_val).sum())\n",
" assert int(''.join(results['Outputs'][var] for var in out_vars)[::-1], 2) == np.asarray(inp_arr_val).sum(), err_str\n",
"print \" \".join([\"Time taken is\" , str(processing_time.mean()),'sec'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Binary Vector Dot Product + Sign Fn"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from matSHEEP import nn_layer as nn\n",
"from tqdm import tqdm\n",
"nb = 10\n",
"samples = 2\n",
"inputs = enc_vec(name='nn_input', nb=nb)\n",
"depth = int(math.ceil(math.log(nb*1.0, 2)))\n",
"outputs = enc_vec(name='nn_outputs', nb=1)\n",
"outputs_sum = enc_vec(name='sum_outputs', nb=depth+1)\n",
"weight = np.asarray(list(map(lambda x : int(x), np.random.uniform(size=nb)> 0.5)))\n",
"layer = nn.linear_layer_1d(name='linear', weight=weight,\n",
" inputs=inputs, outputs=outputs)\n",
"layer_obj = circuit('linear_layer', layer, const_inputs=[])\n",
"layer_obj.write_file(filename='./test_linear.sheep')\n",
"processing_time = np.zeros(samples)\n",
"for idx in tqdm(range(0, samples)):\n",
" inp_arr_val = list(map(lambda x : int(x), np.random.uniform(size=nb)> 0.5))\n",
" inp_file = inputs.get_input_dict(inp_arr_val, write_file=True)\n",
" results = layer_obj.run_circuit(inp_file)\n",
" processing_time[idx] = results['Processing times (s)']['circuit_evaluation']\n",
" out_vars = outputs.get_variables()\n",
" xor_val = (weight == np.asarray([x for x in inp_arr_val]))\n",
" err_str = str(''.join(results['Outputs'][var] for var in out_vars)[::-1]) +\" -- \"+ str(np.asarray(xor_val).sum())\n",
" assert int(''.join(results['Outputs'][var] for var in out_vars)[::-1], 2) == int(np.asarray(xor_val).sum()>nb/2), err_str\n",
"print \" \".join([\"Time taken is\" , str(processing_time.mean()),'sec'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Compare Encrypted Number (binary) with clear text"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from matSHEEP.reusable_modules import compare_cp\n",
"cp_inp_val = [1, 0, 1, 1, 1, 1, 1]\n",
"tgt = 126\n",
"comp_inp = enc_vec(name='cp_inp',nb = len(cp_inp_val))\n",
"out_vec = enc_vec(name='cp_out', nb=1)\n",
"cp_circ = compare_cp(name='cp', inputs=(comp_inp, tgt), outputs=out_vec)\n",
"cp_obj = circuit('cp', cp_circ)\n",
"cp_obj.write_file(filename='./test_cp.sheep')\n",
"inputs_file = comp_inp.get_input_dict(cp_inp_val, write_file=True)\n",
"results = cp_obj.run_circuit(inputs_file)\n",
"processing_time[idx] = results['Processing times (s)']['circuit_evaluation']\n",
"#assert (int(results['Outputs'][out_vec.get_variables()[0]]) == int(int(''.join(map(lambda x : str(x), cp_inp_val)),2) >= tgt))\n",
"if int(results['Outputs'][out_vec.get_variables()[0]]) == 1:\n",
" print str( int(int(''.join(map(lambda x : str(x), cp_inp_val[::-1])),2)))+\"(CP) is greater than \"+str(tgt)+str(\"(PT)\")\n",
"else:\n",
" print str( int(int(''.join(map(lambda x : str(x), cp_inp_val[::-1])),2)))+\"(CP) is smaller than \"+str(tgt)+str(\"(PT)\")\n",
"print \" \".join([\"Time taken is\" , results['Processing times (s)']['circuit_evaluation'],'sec'])\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Fully Connected Layer "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"nb = 10\n",
"samples = 1\n",
"num_out= 3\n",
"depth = int(math.ceil(math.log(nb*1.0, 2)))\n",
"inputs = enc_mat(name='nn_input'+str(idx)+'_', size= (1, nb))\n",
"outputs = enc_mat(name='nn_outputs'+str(idx)+'_', size=(num_out, 1))\n",
"weight = (np.random.uniform(size=(num_out, nb))> 0.5).astype(int)\n",
"layer = nn.linear_layer(name='linear', weight=weight,\n",
" inputs=inputs, outputs=outputs)\n",
"ll_obj = circuit('linear_layer', layer, const_inputs=[])\n",
"ll_obj.write_file(filename='./test_linear.sheep')\n",
"processing_time = np.zeros(samples)\n",
"for idx in tqdm(range(0, samples)):\n",
" inp_arr_val = list(map(lambda x : int(x), np.random.uniform(size=nb*1)> 0.5))\n",
" inp_file = inputs.get_input_dict(inp_arr_val, write_file=True)\n",
" results = ll_obj.run_circuit(inp_file)\n",
" processing_time[idx] = results['Processing times (s)']['circuit_evaluation']\n",
" out_vars = outputs.get_variables()\n",
" xor_val = (weight == np.asarray([x for x in inp_arr_val]))\n",
" #print(xor_val)\n",
" out_bit_vec = np.asarray([int(results['Outputs'][var]) for var in out_vars])\n",
" true_bit_vec = (np.sum(np.asarray(xor_val), axis=1)>nb/2).astype(int)\n",
" assert np.alltrue(out_bit_vec == true_bit_vec)\n",
"print(processing_time.mean())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Convolutional Layer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"start = time.time()\n",
"inp_image = enc_tensor3(name='conv_in', size=(10, 7, 7))\n",
"out_image = enc_tensor3(name='conv_out', size=(10, 3, 3))\n",
"weight = (np.random.uniform(size=(10, 10,5,5))> 0.5).astype(int)\n",
"conv_lyr = nn.conv_layer(name='conv_nn', inputs=inp_image, outputs=out_image, weight=weight)\n",
"nb = reduce(lambda x,y : x*y, inp_image.size)\n",
"layer_obj = circuit('linear_layer', conv_lyr, const_inputs=[])\n",
"layer_obj.write_file(filename='./test_cnn.sheep')\n",
"\n",
"end = time.time()\n",
"print(end - start)\n",
"samples = 1\n",
"processing_time = np.zeros(samples)\n",
"for idx in tqdm(range(0, samples)):\n",
" inp_arr_val = list(map(lambda x : int(x), np.random.uniform(size=nb*1)> 0.5))\n",
" inp_dict = inp_image.get_input_dict(inp_arr_val, write_file=True)\n",
" results = layer_obj.run_circuit(inp_dict)\n",
" processing_time[idx] = results['Processing times (s)']['circuit_evaluation']\n",
"print(processing_time.mean())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Linear Layer time (inp_dim, out_dim)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_time(nb, out, samples=1):\n",
" # Define input matrix, output matrix and weight matrix\n",
" inputs = enc_mat(name='nn_input', size= (1, nb))\n",
" outputs = enc_mat(name='nn_outputs', size=(out, 1))\n",
" weight = (np.random.uniform(size=(out, nb))> 0.5).astype(int)\n",
"\n",
" #Initialize Layer and Circuit\n",
" layer = nn.linear_layer(name='linear', weight=weight,\n",
" inputs=inputs, outputs=outputs)\n",
" ll_obj = circuit('linear_layer', layer, const_inputs=[])\n",
" ll_obj.write_file(filename='./test_linear.sheep')\n",
"\n",
"\n",
" processing_time = np.zeros(samples)\n",
" for idx in tqdm(range(0, samples)):\n",
" \n",
" # Random Input Value\n",
" inp_arr_val = list(map(lambda x : int(x), np.random.uniform(size=nb*1)> 0.5))\n",
" inp_file = inputs.get_input_dict(inp_arr_val, write_file=True)\n",
" \n",
" #Get Results\n",
" results = ll_obj.run_circuit(inp_file)\n",
" processing_time[idx] = results['Processing times (s)']['circuit_evaluation']\n",
" out_vars = outputs.get_variables()\n",
" \n",
" #Check if Input is correct\n",
" xor_val = (weight == np.asarray([x for x in inp_arr_val]))\n",
" out_bit_vec = np.asarray([int(results['Outputs'][var]) for var in out_vars])\n",
" true_bit_vec = (np.sum(np.asarray(xor_val), axis=1)>nb/2).astype(int)\n",
" assert np.alltrue(out_bit_vec == true_bit_vec)\n",
" return processing_time.mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Diabetes\n",
"#### Structure\n",
"$1704\\rightarrow 10 \\rightarrow 1 $ "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Input \n",
"nb = 1704 # Input bits\n",
"samples = 1 #Averaging over\n",
"num_out= 10 # Number of Outputs\n",
"\n",
"#t_1 = get_time(nb, num_out)\n",
"#t_2 = get_time(nb, 1)\n",
"#t_3 = get_time(10, 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Time\n",
"\n",
"* Out Seq $\\rightarrow t_1 + t_3 \\rightarrow$ 288 sec \n",
"* All Parallel $\\rightarrow t_2 + t_3 \\rightarrow $ 29 sec"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# MNIST\n",
"#### Structure\n",
"\n",
"$784 \\rightarrow 2048 \\rightarrow 2048 \\rightarrow 2048 \\rightarrow 10$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# t_1 = get_time(784, 256) \n",
"# t_2 = get_time(2048, 2)\n",
"# t_3 = get_time(2048, 10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### TIming\n",
"* OutSeq\n",
"\n",
"\\begin{align}\n",
"\\mathbf{TIME} &= 8 * \\mathbf{TIME}~(784 \\times 256) + 2 * (1024 * \\mathbf{TIME}~(2048 \\times 2) ) + \\mathbf{TIME}~(2048\\times 10)\\\\\n",
"&= 8 * t_1 + 2 * 1024 * t_2 + t_3\\\\\n",
"&= 8 * 3277.0 + 2 * 1024 * 70 + 348\\\\\n",
"&= 169,924\\mathrm{sec} = 47.2\\mathrm{hr}\n",
"\\end{align}\n",
"\n",
"* All Parallel\n",
"\n",
"\\begin{align}\n",
"\\mathbf{TIME} &= \\dfrac{\\mathbf{TIME}~(784 \\times 256)}{256} + 2 * \\dfrac{1}{2} (\\mathbf{TIME}~(2048 \\times 2) ) + \\dfrac{1}{10}\\mathbf{TIME}~(2048\\times 10)\\\\\n",
"&= \\frac{t_1}{256} + t_2 + \\frac{t_3}{10}\\\\\n",
"&= 12.8 + 70 + 35\\\\\n",
"&= 117.8\\mathrm{sec}\n",
"\\end{align}\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Cancer\n",
"#### Structure\n",
"$90\\rightarrow 1$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t = get_time(90,1, samples=2)\n",
"print(t)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Timings\n",
"\n",
"\n",
"OutSeq = All Parallel = $t = 4\\mathrm{sec}$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_conv_time(inp_image, filter_size):\n",
" out_size = (filter_size[0], \n",
" inp_image[1] - filter_size[2] + 1, \n",
" inp_image[2] - filter_size[3] + 1)\n",
" inp_image = enc_tensor3(name='conv_in', size=inp_image)\n",
" out_image = enc_tensor3(name='conv_out', size=out_size)\n",
" weight = (np.random.uniform(size=filter_size)> 0.5).astype(int)\n",
" conv_lyr = nn.conv_layer(name='conv_nn', inputs=inp_image, outputs=out_image, weight=weight)\n",
" nb = reduce(lambda x,y : x*y, inp_image.size)\n",
" layer_obj = circuit('linear_layer', conv_lyr, const_inputs=[])\n",
" layer_obj.write_file(filename='./test_cnn.sheep')\n",
" samples = 1\n",
" processing_time = np.zeros(samples)\n",
" for idx in tqdm(range(0, samples)):\n",
" inp_arr_val = list(map(lambda x : int(x), np.random.uniform(size=nb*1)> 0.5))\n",
" inp_dict = inp_image.get_input_dict(inp_arr_val, write_file=True)\n",
" results = layer_obj.run_circuit(inp_dict)\n",
" processing_time[idx] = results['Processing times (s)']['circuit_evaluation']\n",
" return processing_time.mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Faces\n",
"\n",
"#### Structure\n",
"\n",
"\n",
"\\begin{align} (1, 50, 50)&\\rightarrow \\mathbf{FILTER}~(32, 32, 10, 10)= \\mathbf{ACTIVATIONS}~(32, 41, 41)\\\\\n",
"&\\rightarrow \\mathbf{FILTER}~(32, 32, 10, 10)= \\mathbf{ACTIVATIONS}~(32, 32, 32)\\\\\n",
"&\\rightarrow \\mathbf{FILTER}~(32, 32, 10, 10)= \\mathbf{ACTIVATIONS}~(32, 23, 23)\\\\\n",
"&\\rightarrow \\mathbf{FILTER}~(32, 32, 10, 10)= \\mathbf{ACTIVATIONS}~(32, 14, 14)\\\\\n",
"&\\rightarrow \\mathbf{FILTER}~(32, 32, 10, 10) \\\\\n",
"&= \\mathbf{ACTIVATIONS}~(1, 5, 5)\\rightarrow 1\n",
"\\end{align}\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# t_1 = get_conv_time(inp_image=(1, 15, 15), filter_size=(32, 1, 10, 10)) # = 1887\n",
"# t_2 = get_conv_time(inp_image=(32, 10, 10), filter_size=(32, 32, 10, 10)) # = 1737\n",
"# t_3 = get_conv_time(inp_image=(32, 12, 12), filter_size=(32, 32, 10, 10)) # = 16020\n",
"# t_4 = get_conv_time(inp_image=(32, 14, 14), filter_size=(1, 32, 10, 10)) # = 1347\n",
"# t_5 = get_time(25,1, samples=2)\n",
"# tt = 0.1 * t_2 + 0.9 * t3/(3 * 3) = 1775"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Timings\n",
"\n",
"* Out Seq\n",
"\n",
"\\begin{align*} \n",
"\\mathbf{TIME} &= tt_1 + tt_2 + t2_3+ tt_4+ tt_5+ tt_6 \\\\\n",
"tt_1 &= t_1 \\times\\frac{ 41 \\times 41}{36} = 88112~\\mathrm{sec}\\\\\n",
"tt_2 &= tt * 32 \\times 32 = 1,817,600~\\mathrm{sec}\\\\\n",
"tt_3 &= tt * 23 \\times 23 = 938,975~\\mathrm{sec} \\\\\n",
"tt_4 &= tt * 14 \\times 14 = 347,900~\\mathrm{sec} \\\\\n",
"tt_5 &= 1347\\\\\n",
"tt_6 &= t5 \\sim 1\\\\\n",
"\\mathbf{TIME} &\\sim 88112 + 1817600 + 938975 + 347900 +1347\\\\\n",
"&= 3,193,934~\\mathrm{sec} \\sim 886.83~\\mathrm{hours} =36.95~\\mathrm{days}\n",
"\\end{align*}\n",
"\n",
"* All Parallel\n",
"\n",
"\\begin{align}\n",
"\\mathbf{TIME} &= \\frac{t_1}{36} + tt * 3 + t4 + t5\\\\\n",
"&= 52.41 + 5325 +1347 + 1 = 1.87~\\mathrm{hour}\n",
"\\end{align}\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```\n",
"The timings are a bit worse here for Faces as\n",
"the binary dot product for a vector of 3200 bits\n",
"seems to increase from 47s to 55s (from previous code to SHEEP).\n",
"\n",
"For a vector of 1024 bits, the timing is exactly same for both codes.\n",
"I suspect this has something to do with TBB vs OpenMP but I am not very\n",
"sure.\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.14"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment