Last active
June 7, 2018 14:15
-
-
Save amartya18x/28c3eb331cafdbffa258548b55a5e0f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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