danielholanda / LeFlow

Enabling Flexible FPGA High-Level Synthesis of Tensorflow Deep Neural Networks
Other
588 stars 101 forks source link

Trying feed AlexNet to LeFlow #9

Closed xzhou40 closed 5 years ago

xzhou40 commented 6 years ago

Hi, I tried to feed AlexNet to LeFlow. The generated 1.ll is in the link below.

https://github.com/xzhou40/alexnet_leflow

There are several errors:

  1. getelementptr has different syntax for LLVM 7 and LLVM3.5, which is not covered in the downgrade script.
  2. After I modified the IR manually to correct getelementptr. Lots of new errors will be created from 4.ll to 5.ll. LeFlow will complain about those error when trying to assemble 7.ll. Error message:

llvm-as: myalexnet_forward_newtf_files/myalexnet_forward_newtf_ir_7.ll:39:20: error: expected value token @temp0 = global i8*), i8** %temps, align zeroinitializer, align 8 ^ Traceback (most recent call last): File "../../src/LeFlow_from2", line 200, in run_leflow(args.file_name,tool_path) File "../../src/LeFlow_from2", line 114, in run_leflow shutil.move(project_folder+project_name+"_ir_7.bc", project_folder+project_name+".prelto.1.bc") File "/usr/lib/python2.7/shutil.py", line 302, in move copy2(src, real_dst) File "/usr/lib/python2.7/shutil.py", line 130, in copy2 copyfile(src, dst) File "/usr/lib/python2.7/shutil.py", line 82, in copyfile with open(src, 'rb') as fsrc: IOError: [Errno 2] No such file or directory: 'myalexnet_forward_newtf_files/myalexnet_forward_newtf_ir_7.bc'

Thank you!

danielholanda commented 6 years ago

Hi xzhou40,

Sorry for the late reply. I was working full-time on a paper, which I finally submitted.

I assume that feeding Alexnet to LeFlow is going to be challenging, since all weights will be a 32-bit floating-point and everything needs to fit into the internal memory of the FPGA. Nevertheless, there are some tricks that we might be able to do to make this work.

Is there any chance you can share your python script with me? I think we need to start from there.

xzhou40 commented 6 years ago

Hi thank you for the reply! Resources on FPGA is one problem. I think there might be some compiling issues as well. I uploaded my version of alexnet below. Weights are on the Homepage described in Readme. https://github.com/xzhou40/alexnet_tf_xla

Thank you very much

danielholanda commented 6 years ago

Hi,

Sorry for the terrible delay to reply to your question. I created a slightly more complex example that should allow you to create hardware for Alexnet using LeFlow. The example shows a network that performs convolution -> maxpool -> convolution -> maxpool -> dense -> dense. It is probably a better idea to modify this example than to try to adapt your old code.

Some good tips to help you debugging if you have any problems are:

import tensorflow as tf
import numpy as np
import sys
sys.path.append('../../src')

import processMif as mif

# This creates a random 32-bit floating point input for your variables
def rand(dim):
    return np.random.random(dim).astype(np.float32)

X = tf.placeholder(tf.float32, [1, 28,28,1])
test_image=rand([1,28,28,1])

conv1_w = tf.Variable(rand([5,5,1,8]))
conv1_b = tf.Variable(rand([8])) 

conv2_w = tf.Variable(rand([5,5,8,16])) 
conv2_b = tf.Variable(rand([16]))

dense1_w = tf.Variable(rand([784, 20])) 
dense1_b = tf.Variable(rand([20]))

dense2_w = tf.Variable(rand([20, 10])) 
dense2_b = tf.Variable(rand([10]))

with tf.Session() as sess:

    # Generating circuit
    with tf.device("device:XLA_CPU:0"):

        # Convolution 1
        conv1 = tf.nn.relu(tf.add(tf.nn.conv2d(X, conv1_w, strides=[1, 1, 1, 1], padding='SAME'),conv1_b))

        # Maxpool 1 
        maxp1=tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)

        # Convolution 2
        conv2 = tf.add(tf.nn.conv2d(maxp1, conv2_w, strides=[1, 1, 1, 1], padding='SAME'),conv2_b)

        # Maxpool 2
        maxp2=tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)

        # Reshaping array
        maxp2_reshaped = tf.nn.relu(tf.reshape(maxp2, shape=[1, 784]))

        # Dense layer 1 
        dense1 = tf.add(tf.matmul(maxp2_reshaped, dense1_w)[0], dense1_b)

        # Dense layer 2
        dense1_reshaped = tf.reshape(dense1, shape=[1, 20])
        y = tf.add(tf.matmul(dense1_reshaped, dense2_w)[0], dense2_b)

    sess.run(tf.global_variables_initializer())
    result = sess.run(y,{X: test_image})

    # Print expected result
    print("Result Calculated: "+str(result))

    # Creating .mif files to initialize the memories
    # To do this, go to <your_file>_ir_7.ll and check the list of params (inputs) and their sizes 
    param8 = dense2_b.eval();
    param7 = dense2_w.eval();
    param6 = dense1_b.eval();
    param5 = dense1_w.eval();
    param4 = conv2_b.eval();
    param3 = conv2_w.eval();
    param2 = conv1_b.eval();
    param1 = test_image;
    param0 = conv1_w.eval();
    mif.createMem([param0,param1,param2,param3,param4,param5,param6,param7,param8])
phatberstromgg commented 4 years ago

Hi @danielholanda This is my code for AlexNet, I just want to classify 2 classes. Is this true following this architecture , esspecially at Dense 6, dense 7 and dense 8. Hope for your help. Thank you.

import tensorflow as tf import numpy as np import sys sys.path.append('../../src')

import processMif as mif

def rand(dim): return np.random.random(dim).astype(np.float32)

X = tf.placeholder(tf.float32, [1, 227, 227, 3]) test_image = rand([1, 227, 227, 3])

conv1_w = tf.Variable(rand([11, 11, 3, 96])) conv1_b = tf.Variable(rand([96]))

conv2_w = tf.Variable(rand([5, 5, 96, 256])) conv2_b = tf.Variable(rand([256]))

conv3_w = tf.Variable(rand([3, 3, 256, 384])) conv3_b = tf.Variable(rand([384]))

conv4_w = tf.Variable(rand([3, 3, 384, 384])) conv4_b = tf.Variable(rand([384]))

conv5_w = tf.Variable(rand([3, 3, 384, 256])) conv5_b = tf.Variable(rand([256]))

dense6_w = tf.Variable(rand([6 6 256, 4096])) dense6_b = tf.Variable(rand([4096]))

dense7_w = tf.Variable(rand([4096, 4096])) dense7_b = tf.Variable(rand([4096]))

dense8_w = tf.Variable(rand([4096, 2])) dense8_b = tf.Variable(rand([2]))

with tf.Session() as sess: with tf.device("device:XLA_CPU:0"):

    #Conv1
    conv1 = tf.nn.relu(tf.add(tf.nn.conv2d(X, conv1_w, strides=[1,4,4,1], padding='SAME'), conv1_b))

    #Maxpool1
    maxp1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[3,3], strides=2)

    #Conv2
    conv2 = tf.nn.relu(tf.add(tf.nn.conv2d(maxp1, conv2_w, strides=[1,1,1,1], padding='SAME'), conv2_b)) 

    #Maxpool2
    maxp2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[3,3], strides=2)

    #Conv3
    conv3 = tf.nn.relu(tf.add(tf.nn.conv2d(maxp2, conv3_w, strides=[1,1,1,1], padding='SAME'), conv3_b))

    #Conv4
    conv4 = tf.nn.relu(tf.add(tf.nn.conv2d(conv3, conv4_w, strides=[1,1,1,1], padding='SAME'), conv4_b))

    #Conv5
    conv5 = tf.nn.relu(tf.add(tf.nn.conv2d(conv4, conv5_w, strides=[1,1,1,1], padding='SAME'), conv5_b))

    #Maxpool5
    maxp5 = tf.layers.max_pooling2d(inputs=conv5, pool_size=[3,3], strides=2)

    #Reshape
    maxp5_reshaped = tf.nn.relu(tf.reshape(maxp5, shape=[1,6*6*256]))

    #Dense6
    dense6 = tf.nn.relu(tf.add(tf.matmul(maxp5_reshaped, dense6_w)[0], dense6_b))

    #Dense7
    dense6_reshaped = tf.reshape(dense6, shape=[1, 4096])
    dense7 = tf.nn.relu(tf.add(tf.matmul(dense6_reshaped, dense7_w)[0], dense7_b))

    #Dense8
    dense7_reshaped = tf.reshape(dense7, shape=[1,4096])
    y = tf.add(tf.matmul(dense7_reshaped, dense8_w)[0], dense8_b)

sess.run(tf.global_variables_initializer())
result = sess.run(y,{X: test_image})

print("Result:"+str(result))