 }
 
 void TrainModel() {
+    bool eof_flag = false;
     long a, b, c, d;
-    FILE *fo;
+    unsigned int *gpu_vocab, *gpu_expTable, *gpu_syn0, *gpu_syn1;
+    FILE *fi, *fo;
     pthread_t *pt = (pthread_t *)malloc(num_threads * sizeof(pthread_t));
     printf("Starting training using file %s\n", train_file);
     starting_alpha = alpha;
   
-    profile("build vocab begin");
+    profile("/ build vocab");
     if (read_vocab_file[0] != 0) ReadVocab(); else LearnVocabFromTrainFile();
-    profile("build vocab end");
-
-    profile("save vocab begin");
+    profile("\\ build vocab");
+
+    profile("/ save vocab");
     if (save_vocab_file[0] != 0) SaveVocab();
-    profile("save vocab end");
+    profile("\\ save vocab");
       
     if (output_file[0] == 0) return;
     InitNet();
     if (negative > 0) InitUnigramTable();
 
-    profile("training model begin");
+    profile("/ memcopy vocab");
+    CUDA_CALL(cudaMalloc((void **) &gpu_vocab, (long long) vocab_size * sizeof(*vocab)));
+    CUDA_CALL(cudaMemcpy(gpu_vocab, vocab, (long long) vocab_size * sizeof(*vocab), cudaMemcpyHostToDevice))
+    profile("\\ memcopy vocab");
+
+    //profile("memcopy vocab_hash");
+    //profile("memcopy vocab_hash");
+
+    profile("/ memcopy expTable");
+    CUDA_CALL(cudaMalloc((void **) &gpu_expTable, (long long) EXP_TABLE_SIZE * sizeof(*expTable)));
+    CUDA_CALL(cudaMemcpy(gpu_expTable, expTable, (long long) EXP_TABLE_SIZE * sizeof(*expTable), cudaMemcpyHostToDevice));
+    profile("\\ memcopy expTable");
+
+    profile("/ memcopy syn0");
+    CUDA_CALL(cudaMalloc((void **) &gpu_syn0, (long long) vocab_size * layer1_size * sizeof(*syn0)));
+    CUDA_CALL(cudaMemcpy(gpu_syn0, syn0, (long long) vocab_size * layer1_size * sizeof(*syn0), cudaMemcpyHostToDevice));
+    profile("\\ memcopy syn0");
+
+    profile("/ memcopy syn1");
+    CUDA_CALL(cudaMalloc((void **) &gpu_syn1, (long long) vocab_size * layer1_size * sizeof(*syn1)));
+    CUDA_CALL(cudaMemcpy(gpu_syn1, syn1, (long long) vocab_size * layer1_size * sizeof(*syn1), cudaMemcpyHostToDevice));
+    profile("\\ memcopy syn1");
+
+    //profile("/ memcopy syn1neg");
+    //profile("\\ memcopy syn1neg");
+
+    profile("/ cpu malloc cache");
+    cpu_cache = (long long *) malloc((long long) CACHE_SIZE_BY_BYTES); // cache_size by GB
+    profile("\\ cpu malloc cache");
+
+    profile("/ gpu malloc cache");
+    CUDA_CALL(cudaMalloc((void **) &gpu_cache, (long long) CACHE_SIZE_BY_BYTES)); // cache_size by GB
+    profile("\\ gpu malloc cache");
+
+    fi = fopen(train_file, "rb");
+    while (!eof_flag) {
+        profile("/ charge cache");
+        eof_flag = charge_cpu_cache(fi);
+        charge_gpu_cache();
+        profile("\\ charge cache");
+        launch_kernel();
+    }
+    fclose(fi);
+
+    profile("/ retrieve syn0");
+    profile("\\ retrieve syn0");
+
+    profile("/ retrieve syn1");
+    profile("\\ retrieve syn1");
+
+    pause();
+
+    profile("/ training model");
     start = clock();
     for (a = 0; a < num_threads; a++) pthread_create(&pt[a], NULL, TrainModelThread, (void *)a);
     for (a = 0; a < num_threads; a++) pthread_join(pt[a], NULL);
-    profile("training model end");
-
-    profile("saving model begin");
+    profile("\\ training model");
+
+    profile("/ saving model");
     fo = fopen(output_file, "wb");
     if (classes == 0) {
         // Save the word vectors

char train_file[MAX_STRING], output_file[MAX_STRING];
char save_vocab_file[MAX_STRING], read_vocab_file[MAX_STRING];
struct vocab_word *vocab;
int binary = 0, cbow = 1, debug_mode = 2, window = 5, min_count = 5, num_threads = 12, min_reduce = 1;
int *vocab_hash;
long long vocab_max_size = 1000, vocab_size = 0, layer1_size = 100;
long long train_words = 0, word_count_actual = 0, iter = 5, file_size = 0, classes = 0;
real alpha = 0.025, starting_alpha, sample = 1e-3;
real *syn0, *syn1, *syn1neg, *expTable;

        free(cent);
        free(cl);
    }
    profile("\\ saving model");
  
    fclose(fo);
}
