開源評測系統hustoj-程式碼解讀 及 快速安裝
/* * Copyright 2008 sempr <[email protected]> * * Refacted and modified by zhblue<[email protected]> * Bug report email [email protected] * * This file is part of HUSTOJ. * * HUSTOJ is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * HUSTOJ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HUSTOJ. if not, see <http://www.gnu.org/licenses/>. */ #include <time.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <unistd.h> #include <syslog.h> #include <errno.h> #include <fcntl.h> #include <stdarg.h> #include <mysql/mysql.h> #include <sys/wait.h> #include <sys/stat.h> #include <signal.h> #include <sys/resource.h> static int DEBUG = 0; //是否啟用除錯,來檢視日誌執行記錄,預設0,不啟用 #define BUFFER_SIZE 1024 #define LOCKFILE "/var/run/judged.pid" #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) #define STD_MB 1048576 #define OJ_WT0 0 #define OJ_WT1 1 #define OJ_CI 2 #define OJ_RI 3 #define OJ_AC 4 #define OJ_PE 5 #define OJ_WA 6 #define OJ_TL 7 #define OJ_ML 8 #define OJ_OL 9 #define OJ_RE 10 #define OJ_CE 11 #define OJ_CO 12 static char host_name[BUFFER_SIZE]; static char user_name[BUFFER_SIZE]; static char password[BUFFER_SIZE]; static char db_name[BUFFER_SIZE]; static char oj_home[BUFFER_SIZE]; static char oj_lang_set[BUFFER_SIZE]; static int port_number; static int max_running; static int sleep_time; static int sleep_tmp; static int oj_tot; static int oj_mod; static int http_judge = 0; static char http_baseurl[BUFFER_SIZE]; static char http_username[BUFFER_SIZE]; static char http_password[BUFFER_SIZE]; static bool STOP = false; static MYSQL *conn; static MYSQL_RES *res; //mysql讀取結果集,在_get_http/mysql_jobs()中被更新 static MYSQL_ROW row; //static FILE *fp_log; static char query[BUFFER_SIZE];//在init_mysql_conf中更新,固定取2倍最大判題客戶端的待評判題目solution_id void call_for_exit(int s) { STOP = true; printf("Stopping judged...\n"); } void write_log(const char *fmt, ...) { va_list ap; char buffer[4096]; // time_t t = time(NULL); // int l; sprintf(buffer, "%s/log/client.log", oj_home); FILE *fp = fopen(buffer, "a+"); if (fp == NULL) { fprintf(stderr, "openfile error!\n"); system("pwd"); } va_start(ap, fmt); vsprintf(buffer, fmt, ap); fprintf(fp, "%s\n", buffer); if (DEBUG) printf("%s\n", buffer); va_end(ap); fclose(fp); } int after_equal(char * c) { int i = 0; for (; c[i] != '\0' && c[i] != '='; i++) ; return ++i; } void trim(char * c) { char buf[BUFFER_SIZE]; char * start, *end; strcpy(buf, c); start = buf; while (isspace(*start)) start++; end = start; while (!isspace(*end)) end++; *end = '\0'; strcpy(c, start); } bool read_buf(char * buf, const char * key, char * value) { if (strncmp(buf, key, strlen(key)) == 0) { strcpy(value, buf + after_equal(buf)); trim(value); if (DEBUG) printf("%s\n", value); return 1; } return 0; } void read_int(char * buf, const char * key, int * value) { char buf2[BUFFER_SIZE]; if (read_buf(buf, key, buf2)) sscanf(buf2, "%d", value); } // read the configue file void init_mysql_conf() { FILE *fp = NULL; char buf[BUFFER_SIZE]; host_name[0] = 0; user_name[0] = 0; password[0] = 0; db_name[0] = 0; port_number = 3306; max_running = 3; sleep_time = 1; oj_tot = 1; oj_mod = 0; strcpy(oj_lang_set, "0,1,2,3,4,5,6,7,8,9,10"); fp = fopen("./etc/judge.conf", "r"); if (fp != NULL) { while (fgets(buf, BUFFER_SIZE - 1, fp)) { read_buf(buf, "OJ_HOST_NAME", host_name); read_buf(buf, "OJ_USER_NAME", user_name); read_buf(buf, "OJ_PASSWORD", password); read_buf(buf, "OJ_DB_NAME", db_name); read_int(buf, "OJ_PORT_NUMBER", &port_number); read_int(buf, "OJ_RUNNING", &max_running); read_int(buf, "OJ_SLEEP_TIME", &sleep_time); read_int(buf, "OJ_TOTAL", &oj_tot); read_int(buf, "OJ_MOD", &oj_mod); read_int(buf, "OJ_HTTP_JUDGE", &http_judge); read_buf(buf, "OJ_HTTP_BASEURL", http_baseurl); read_buf(buf, "OJ_HTTP_USERNAME", http_username); read_buf(buf, "OJ_HTTP_PASSWORD", http_password); read_buf(buf, "OJ_LANG_SET", oj_lang_set); } sprintf(query, "SELECT solution_id FROM solution WHERE language in (%s) and result<2 and MOD(solution_id,%d)=%d ORDER BY result ASC,solution_id ASC limit %d", oj_lang_set, oj_tot, oj_mod, max_running * 2); sleep_tmp = sleep_time; // fclose(fp); } } //當有代評測提交,並且程序數允許的情況下,建立新的子程序呼叫該評測函式 //輸入:代評測提交的solution_id, 子程序在ID[]中的儲存位置 i void run_client(int runid, int clientid) { char buf[BUFFER_SIZE], runidstr[BUFFER_SIZE]; //在Linux系統中,Resouce limit指在一個程序的執行過程中,它所能得到的資源的限制, //比如程序的core file的最大值,虛擬記憶體的最大值等 ,這是執行時間,記憶體大小實現的關鍵 /* 結構體中 rlim_cur是要取得或設定的資源軟限制的值,rlim_max是硬限制 這兩個值的設定有一個小的約束: 1) 任何程序可以將軟限制改為小於或等於硬限制 2)任何程序都可以將硬限制降低,但普通使用者降低了就無法提高,該值必須等於或大於軟限制 3) 只有超級使用者可以提高硬限制 setrlimit(int resource,const struct rlimit rlptr);返回:若成功為0,出錯為非0 RLIMIT_CPU:CPU時間的最大量值(秒),當超過此軟限制時向該程序傳送SIGXCPU訊號 RLIMIT_FSIZE:可以建立的檔案的最大位元組長度,當超過此軟限制時向程序傳送SIGXFSZ */ struct rlimit LIM; LIM.rlim_max = 800; LIM.rlim_cur = 800; setrlimit(RLIMIT_CPU, &LIM);//cpu執行時間限制 LIM.rlim_max = 80 * STD_MB; LIM.rlim_cur = 80 * STD_MB; setrlimit(RLIMIT_FSIZE, &LIM);//可檔案大小限制,防止惡意程式的嗎? LIM.rlim_max = STD_MB << 11;//左移11 STD_MB是2^20 MB 2^11MB 2GB機器起碼的2GB虛擬記憶體? LIM.rlim_cur = STD_MB << 11; setrlimit(RLIMIT_AS, &LIM);//最大執行的虛擬記憶體大小限制 LIM.rlim_cur = LIM.rlim_max = 200; setrlimit(RLIMIT_NPROC, &LIM);//每個實際使用者ID所擁有的最大子程序數,這些都是為了防止惡意程式的吧?? //buf[0]=clientid+'0'; buf[1]=0; sprintf(runidstr, "%d", runid);//轉換成字元?還是字串? sprintf(buf, "%d", clientid); //write_log("sid=%s\tclient=%s\toj_home=%s\n",runidstr,buf,oj_home); //sprintf(err,"%s/run%d/error.out",oj_home,clientid); //freopen(err,"a+",stderr); if (!DEBUG) execl("/usr/bin/judge_client", "/usr/bin/judge_client", runidstr, buf, oj_home, (char *) NULL); else //返回值:如果執行成功則函式不會返回, 執行失敗則直接返回-1, 失敗原因存於errno 中. //execl()其中字尾"l"代表list也就是引數列表的意思,第一引數path字元指標所指向要執行的檔案路徑, //接下來的引數代表執行該檔案時傳遞的引數列表:argv[0],argv[1]... 最後一個引數須用空指標NULL作結束。 // 執行/bin目錄下的ls, 第一引數為程式名ls, 第二個引數為"-al", 第三個引數為"/etc/passwd" //execl("/bin/ls", "ls", "-al", "/etc/passwd", (char *) 0); //這裡第一個引數為程式名稱judge_client,第二個引數為代評測題目id, 第三個為本程序pid儲存位置,第四個引數為oj目錄 //預設/home/judge,第五個引數為“debug” execl("/usr/bin/judge_client", "/usr/bin/judge_client", runidstr, buf, oj_home, "debug", (char *) NULL); //exit(0); } //執行sql語句成功返回1,否則返回0 //並且關閉是否conn,它在init裡初始化開始的 int executesql(const char * sql) { if (mysql_real_query(conn, sql, strlen(sql))) { if (DEBUG) write_log("%s", mysql_error(conn)); sleep(20); conn = NULL; return 1; } else return 0; } int init_mysql() { if (conn == NULL) { conn = mysql_init(NULL); // init the database connection /* connect the database */ const char timeout = 30; mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout); if (!mysql_real_connect(conn, host_name, user_name, password, db_name, port_number, 0, 0)) { if (DEBUG) write_log("%s", mysql_error(conn)); sleep(2); return 1; } else { return 0; } } else { return executesql("set names utf8"); } } FILE * read_cmd_output(const char * fmt, ...) { char cmd[BUFFER_SIZE]; FILE * ret = NULL; va_list ap; va_start(ap, fmt); vsprintf(cmd, fmt, ap); va_end(ap); //if(DEBUG) printf("%s\n",cmd); ret = popen(cmd, "r"); return ret; } int read_int_http(FILE * f) { char buf[BUFFER_SIZE]; fgets(buf, BUFFER_SIZE - 1, f); return atoi(buf); } bool check_login() { const char * cmd = "wget --post-data=\"checklogin=1\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s/admin/problem_judge.php\""; int ret = 0; FILE * fjobs = read_cmd_output(cmd, http_baseurl); ret = read_int_http(fjobs); pclose(fjobs); return ret > 0; } void login() { if (!check_login()) { char cmd[BUFFER_SIZE]; sprintf(cmd, "wget --post-data=\"user_id=%s&password=%s\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s/login.php\"", http_username, http_password, http_baseurl); system(cmd); } } int _get_jobs_http(int * jobs) { login(); int ret = 0; int i = 0; char buf[BUFFER_SIZE]; const char * cmd = "wget --post-data=\"getpending=1&oj_lang_set=%s&max_running=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s/admin/problem_judge.php\""; FILE * fjobs = read_cmd_output(cmd, oj_lang_set, max_running, http_baseurl); while (fscanf(fjobs, "%s", buf) != EOF) { //puts(buf); int sid = atoi(buf); if (sid > 0) jobs[i++] = sid; //i++; } pclose(fjobs); ret = i; while (i <= max_running * 2) jobs[i++] = 0; return ret; return ret; } //功能:取得待評測題目資訊到jobs陣列 //輸入:int * jobs :儲存solution_id/runid //輸出:如果查詢成功則返回:要評測題目數量 //如果查詢待判題目不成功則返回0 int _get_jobs_mysql(int * jobs) { //mysql.h //如果查詢資料包括二進位制或者更快速度 用這個 //如果執行成功,返回0;不成功非0 if (mysql_real_query(conn, query, strlen(query))) { if (DEBUG) write_log("%s", mysql_error(conn)); sleep(20); return 0; } //mysql.h //返回具有多個結果的MYSQL_RES結果集合。如果出現錯誤,返回NULL //具體參見百度 res = mysql_store_result(conn); int i = 0; int ret = 0; //遍歷結果集mysql_fetch_row() while ((row = mysql_fetch_row(res)) != NULL) { jobs[i++] = atoi(row[0]); } ret = i; //要評測jobs末端 如 0 1 2 有資料,則i=3代表資料 while (i <= max_running * 2) jobs[i++] = 0; //設定的最大工作數目為max_running*2,將0-8置位0共9個 max_running*2+1陣列開這麼大 return ret; return ret; } int get_jobs(int * jobs) { if (http_judge) { //web和core預設連線方式:資料庫,web插入solution,core輪訓/更新solution-result,web輪訓solution-result return _get_jobs_http(jobs); } else return _get_jobs_mysql(jobs);//讀取要判題的任務數量 } //更新初始化solution表格 //更新成功返回1;否則0 // 疑問:OJ_CI為2,and result < 2這句怎麼都是不成立,這個Sql語句怎麼都不會執行成功才對啊 //用limit 1加了一層保障。避免where 條件出現異常時,錯誤更新影響太多。 //不知道php初始寫多少,但是呼叫給的引數為2啊,不懂!!!! bool _check_out_mysql(int solution_id, int result) { char sql[BUFFER_SIZE]; //sql語句儲存 sprintf(sql, "UPDATE solution SET result=%d,time=0,memory=0,judgetime=NOW() WHERE solution_id=%d and result<2 LIMIT 1", result, solution_id); //執行sql語句,成功返回0;否則非0 if (mysql_real_query(conn, sql, strlen(sql))) { syslog(LOG_ERR | LOG_DAEMON, "%s", mysql_error(conn)); return false; } else { //影響行數,更新數大於0,執行成功,返回1,否則0 if (mysql_affected_rows(conn) > 0ul) return true; else return false; } } bool _check_out_http(int solution_id, int result) { login(); const char * cmd = "wget --post-data=\"checkout=1&sid=%d&result=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s/admin/problem_judge.php\""; int ret = 0; FILE * fjobs = read_cmd_output(cmd, solution_id, result, http_baseurl); fscanf(fjobs, "%d", &ret); pclose(fjobs); return ret; } //初始更新solution表 //依據引數不同執行不同的更新函式 bool check_out(int solution_id, int result) { if (http_judge) { return _check_out_http(solution_id, result); } else return _check_out_mysql(solution_id, result); } int work() { // char buf[1024]; static int retcnt = 0;//統計 已經 完成評測次數 int i = 0; static pid_t ID[100]; //short型別的巨集定義,程序表中的索引項,程序號;儲存正在執行的子程序pid static int workcnt = 0;//統計 現用 judge_client程序數量 int runid = 0; //solution_id,測試執行編號 int jobs[max_running * 2 + 1];//max_running 從judge.conf獲取,一般為4,這裡設定為工作目錄:9 pid_t tmp_pid = 0; //for(i=0;i<max_running;i++){ // ID[i]=0; //} //sleep_time=sleep_tmp; /* get the database info */ if (!get_jobs(jobs)) //如果讀取失敗或者要評測題目數量為0,jobs[]被置為:1001,1002,0,...0;預設9位 retcnt = 0; /* exec the submit *///遍歷評測每個solution_id的題目,只負責把所以題目全部投入到新的評判程序裡 //不管是否評測完成 for (int j = 0; jobs[j] > 0; j++) { runid = jobs[j]; //讀取solution_id,待評測提交題目id //老式併發處理中,預設oj_tot 為 1 oj_mod 為0,在init_sql_conf中設定 所以無用 if (runid % oj_tot != oj_mod) continue; if (DEBUG) //除錯用預設0 無用 write_log("Judging solution %d", runid); //workcnt 為static 變數,相當於死鎖,統計現用run_client程序 數目 //本if 等待可用 子程序,並且用 i 騰出儲存 新子程序的位置 if (workcnt >= max_running) { // if no more client can running //如果達到了可用最大程序數目,那麼等待一個子程序結束 //waitpid,參考linux 下 c 語言程式設計下的 程序管理 //waitpid()會暫時停止目前程序的執行,直到有訊號來到或子程序結束 //pid_t waitpid(pid_t pid,int * status,int options); //pid=-1 代表任意子程序;status 取回子程序識別碼,這裡不需要所以NULL; //引數options提供了一些額外的選項來控制waitpid,比如不等待繼續執行,這裡0代表不使用,程序掛起 //如果 有子程序已經結束,那麼執行到這裡的時候會直接跳過,子程序也會由殭屍程序釋放 //返回結束的子程序pid tmp_pid = waitpid(-1, NULL, 0); // wait 4 one child exit workcnt--;//子程序結束了個,那麼現用judge_client數量減一 retcnt++;//評測完成數加1 //清除儲存在 ID[]裡的已經結束的子程序資訊 for (i = 0; i < max_running; i++) // get the client id if (ID[i] == tmp_pid) break; // got the client id ID[i] = 0; } else { // have free client for (i = 0; i < max_running; i++) // find the client id if (ID[i] == 0) break; // got the client id } //其實這裡worknct<max_running 一定成立,除非waitpid()出錯 //check_out:更新初始化表,但是怎麼都不該執行成功才對的啊,為什麼還能成功呢 //如果可以開始新的子程序進行評測 if (workcnt < max_running && check_out(runid, OJ_CI)) { workcnt++;//正執行子程序數目加1----這裡是不是太早了,子程序建立一定能成功????? //應該在子程序裡更新這個數值吧 ID[i] = fork(); //建立子程序 ,將子程序pid返回給父程序,將0返回給子程序 // start to fork //這句寫的覺得難理解,父程序會將其更新為新程序pid //子程序呢,建立之初會更新為0,那到底是多少??????? //按照程式,子程序會完整複製父程序的程式碼,資料,堆疊 //那麼如果是父程序在執行那麼ID[i] 不為0而是子程序pid //如果是子程序的在執行,那麼資料段又是ID[i]為0???? //那static 的作用呢 if (ID[i] == 0) {//如果成立,那麼代表是在執行子程序程式碼,執行run_judge_client if (DEBUG) write_log("<<=sid=%d===clientid=%d==>>\n", runid, i); run_client(runid, i); //在子程序裡更新ID[0]=pid // if the process is the son, run it exit(0);//子程序執行完畢退出0,父程序不會執行這段if ,在run_client裡程序會跳轉到execl(judge_client) //執行成功不返回,不成功返回非0,儲存在erro裡,那麼這裡又是怎麼執行到的,子程序如何退出的?????? } } else {//理論上,在上個if裡已經保證了這裡為ID[i] = 0,這裡估計是為了進一步保證 ID[i] = 0; } } //把本次輪訓到的代評測題目全部投入評測後 //在非掛起等待子程序的結束,如果有子程序評測完成結束 //在上個的for裡,當可用程序沒有的時候,那麼就必須等其中一個程序結束,那麼才能繼續執行,哪怕在for裡已經有 // 子程序結束是殭屍程序了,只要workcnt<max_running,那麼就也不處理子殭屍程序的回收問題,而是優先投入新的子程序 //進行評測 //那麼子殭屍程序 誰來回收,何時回收,怎麼回收,總不能等可用的全成了殭屍程序,在for裡用到的時候在進行回收吧 //如果可用程序數開的特別大,而一直沒有使用者提交,那豈不是,執行一段時間後,系統肯定會一直有max_running個程序的 //資源被佔用,而且大大大99%部分都是死的子殭屍程序,for只是用幾個收幾個,而不管也沒法管其他的,因為for只有當 //有評測任務的時候才會執行到,大部分沒有使用者提交程式評測的輪詢時間段裡,不順手回收下,豈不可惜!!! //所以就是while()要完成的任務,父程序執行到這裡的時候,掃一眼是否有待回收子殭屍程序,有就 順手回收一個; // 因為不知道有多少待回收的,什麼時候要回收;所以只且只能在這個輪詢時間段裡回收一個 //這個while,純粹是順手牽羊行為,當然也有更新評測完成數量的重要任務~~~ /* 如果使用了WNOHANG引數呼叫waitpid,即使沒有子程序退出,它也會立即返回,不會像wait那樣永遠等下去 1、當正常返回的時候,waitpid返回收集到的子程序的程序ID; 2、如果設定了選項WNOHANG,而呼叫中waitpid發現沒有已退出的子程序可收集,則返回0; 3、如果呼叫中出錯,則返回-1,這時errno會被設定成相應的值以指示錯誤所在; */ while ((tmp_pid = waitpid(-1, NULL, WNOHANG)) > 0) { workcnt--; retcnt++; for (i = 0; i < max_running; i++) // get the client id if (ID[i] == tmp_pid) break; // got the client id ID[i] = 0; printf("tmp_pid = %d\n", tmp_pid); } //釋放資料庫資源 //這裡commit的呼叫,不知道是為了關閉conn,還是資料庫不支援自動commit //還是徹底縮小日誌,不給機會rollback,待學習?????? if (!http_judge) { mysql_free_result(res); // free the memory executesql("commit"); } if (DEBUG && retcnt) write_log("<<%ddone!>>", retcnt); //free(ID); //free(jobs); //返回已經評測的次數 return retcnt; } int lockfile(int fd) { struct flock fl; fl.l_type = F_WRLCK; fl.l_start = 0; fl.l_whence = SEEK_SET; fl.l_len = 0; return (fcntl(fd, F_SETLK, &fl)); } int already_running() { int fd; char buf[16]; fd = open(LOCKFILE, O_RDWR | O_CREAT, LOCKMODE); if (fd < 0) { syslog(LOG_ERR | LOG_DAEMON, "can't open %s: %s", LOCKFILE, strerror(errno)); exit(1); } if (lockfile(fd) < 0) { if (errno == EACCES || errno == EAGAIN) { close(fd); return 1; } syslog(LOG_ERR | LOG_DAEMON, "can't lock %s: %s", LOCKFILE, strerror(errno)); exit(1); } ftruncate(fd, 0); sprintf(buf, "%d", getpid()); write(fd, buf, strlen(buf) + 1); return (0); } int daemon_init(void) { pid_t pid; if ((pid = fork()) < 0) return (-1); else if (pid != 0) exit(0); /* parent exit */ /* child continues */ setsid(); /* become session leader */ chdir(oj_home); /* change working directory */ umask(0); /* clear file mode creation mask */ close(0); /* close stdin */ close(1); /* close stdout */ close(2); /* close stderr */ return (0); } int main(int argc, char** argv) { DEBUG = (argc > 2); if (argc > 1) strcpy(oj_home, argv[1]); else strcpy(oj_home, "/home/judge"); chdir(oj_home); // change the dir if (!DEBUG) daemon_init();//建立一個daemon守護程序 if (strcmp(oj_home, "/home/judge") == 0 && already_running()) { syslog(LOG_ERR | LOG_DAEMON, "This daemon program is already running!\n"); return 1; } // struct timespec final_sleep; // final_sleep.tv_sec=0; // final_sleep.tv_nsec=500000000; init_mysql_conf(); // set the database info signal(SIGQUIT, call_for_exit); signal(SIGKILL, call_for_exit); signal(SIGTERM, call_for_exit); int j = 1; while (1) { // start to run //這個while的好處在於,只要一有任務就抓緊佔用系統優先把所以任務處理完成,哪怕會空迴圈幾次的可能存在 //但是沒有任務後,就會進入到“懶散”的 休息sleep(time)後再輪詢是不是有任務,釋放系統的資源,避免Damon一直 //死迴圈佔用系統 while (j && (http_judge || !init_mysql())) { j = work();//如果讀取失敗或者沒有要評測的資料,那麼返回0,利用那麼有限的幾個程序來評測無限的任務量 } sleep(sleep_time); j = 1; } return 0; }
部落格- 學院
- 下載
- 更多 論壇 問答 活動 碼雲 商城
相關推薦
開源評測系統hustoj-程式碼解讀 及 快速安裝
/* * Copyright 2008 sempr <[email protected]> * * Refacted and modified by zhblue<[email protected]> * Bug report email [email&
開源評測系統hustoj-原始碼解讀2
讀的痛苦又快樂。。。 // // File: main.cc // Author: sempr // refacted by zhblue /* * Copyright 2008 sempr <[email protected]> * *
freeModbus程式碼解讀及移植筆記
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
開源釋出:VS程式碼段快捷方式及視覺化除錯快速部署工具
前言: 很久前,我發過兩篇文章,分別介紹自定義程式碼版和視覺化除錯: 具體可以用兩張圖來表示: 1:自定義程式碼片斷: 2:視覺化除錯工具: 問題來源: 某次,我發現自己的視覺化除錯的類庫有點舊,想更新一下,卻發現: 電腦上安裝了VS2005、VS2008、Vs2012幾個版
【深度學習】ResNet解讀及程式碼實現
簡介 ResNet是何凱明大神在2015年提出的一種網路結構,獲得了ILSVRC-2015分類任務的第一名,同時在ImageNet detection,ImageNet localization,COCO detection和COCO segmentation等任務中均獲得了第一名,在當
一對一聊天系統中登入頁面程式碼設定及相關介面
今天我們來講一下一對一聊天系統中關於手機號碼登入及三方登入的程式碼解決方案,從介面到介面。 一、登入介面 1v1demo的登入,首先要從介面說起(請看下圖)。 1、先用RelativeLayout包裹整個介面 2、接著用上兩個ImagView 3、一個載入底部gif另一個放置帶logo的透明
springcloud微服務多使用者商城系統java_程式碼開源_B2B電商系統_B2C電商系統
通過Spring Cloud構建PC+微信+APP+雲服務的雲商平臺系統,其中包括B2B、B2C、C2C、O2O、新零售、直播電商等子平臺,之前我們講了很多關於Spring Cloud的概念文章,從本節開始,我們會以分散式微服務電子商務平臺為案例,逐步給大家講解如何構建完整的電子商務雲平臺。
騰訊開源的Paxos庫PhxPaxos程式碼解讀---Prepare階段(一)
簡單的畫了一下PhxPaxos在Prepare階段的邏輯,主要是正常的邏輯,異常邏輯和超時後面再寫了; 熟悉PhxPaxos程式碼最好的方法是編譯執行sample目錄下的三個例子,編譯方法在另一篇部落格已經寫了,這裡忽略; 一: Proposor在Pre
開源的線上評測系統——Vakuum
https://github.com/BYVoid/vakuum 簡介 Vakuum是一個基於Linux+PHP的線上評測系統(Online Judge),主要面向資訊學競賽(OI)和ACM/ICPC。 功能 線上評測 使
CCF2017-9-1試題(打醬油)原創程式碼,執行沒問題,CCF評測系統通過100分
#include<iostream> using namespace std; int main(){int result,c,n;cin>>n;//n為輸入買醬油的錢if(n>=30&&n<=50){result=(n-
Windows系統關機及快速關機原理
開啟工作管理員,按住“Ctrl”鍵的同時,再單擊工作管理員視窗中的選單“關機→關閉”命令時,系統會快速地被關閉,同樣,在按住“Ctrl”鍵時,選擇其他命令(例如重新啟動)時,也會達到快速執行該命令的目的。 同時,也出現了像SuperFast Shutdown一樣的
DataCastle[猜你喜歡]推薦系統競賽——Kuhung思路及程式碼
概況介紹 我是參加DataCastle[猜你喜歡]推薦系統的kuhung。在截止競賽日期的測評榜中,我的團隊——猜你不喜歡,以7.86565的最終成績,位居第二。接下來我將分享我的比賽心得及才賽程式碼。 賽題感想 在本次比賽中,DataCastl
變分自編碼(VAE)及程式碼解讀
這幾天在看GAN模型的時候,順便關注了另外一種生成模型——VAE。其實這種生成模型在早幾年就有了,而且有了一些應用。著名黑客George Hotz在其開源的自主駕駛專案中就應用到了VAE模型。這其中的具體應用在我上一篇轉載的部落格comma.ai中有詳細介紹。在對VAE基本原
softmax理論及程式碼解讀——UFLDL
前言 其實,在最初比較疑惑的問題是:softmax的迴歸和分類到底是不是一個解法,或者它倆是不是一個知識?然後在一些部落格中發現,softmax有時候也稱為softmax分類迴歸器,而且在機器學習的定義中,迴歸問題通常用來預測一個值,如預測房價或者未來的天
騰訊開源的 Paxos庫 PhxPaxos 程式碼解讀---Accept階段(一)
騰訊開源的 Paxos庫 PhxPaxos 程式碼解讀---Accept階段(一) 在看Accept階段程式碼之前, 我們再回想一下 Basic Paxos演算法; 1. Basic Paxos 演算法是為了使叢集中的Acc
windows系統快速安裝node版本管理工具NVM及簡單操作
NVM是一個node版本管理控制工具,它能夠幫助你在同一個作業系統內切換不同node版本環境。這對於我們執行那些對node版本有要求的專案是非常有幫助的。一、下面介紹一種快速在windows系統安裝NVM的方法:1.nvm-windows下載地址:傳送門2.下載nvm-set
二值RBM與實值RBM理論及程式碼解讀
1. 前言 雖然推導過二值形式的RBM,但是對於可見層為實值的輸入還是半知半解的。最近寫個深度學習相關綜述,看了一些關於RBM的文獻,這裡做一下對比總結。但是不傾向於對實值RBM的推導,而是相關程式碼的實現。 2. RBM回顧 RBM是具有特殊結構的玻
android系統版本程式碼的下載、編譯及釋出
不積跬步無以至千里 一、程式碼的下載 1、建立資料夾 在伺服器的個人賬戶下建立一個此係統版本的專用資料夾(F9)(事先宣告這是Q9的專案) mkdir F9 2、設定git資訊 git config –global user.email
r-cnn系列程式碼編譯及解讀(1)
本系列針對RBG在github上的fast r-cnn程式碼,做安裝配置及解讀工作 本文解決由於CAFFE版本的更新導致的fast r-cnn編譯失敗的問題 相關檔案下載 假定機器已經安裝配置好caffe環境(最新的版本使用CUDA8 + cudn
開源分散式系統-TFS-安裝及使用簡介
依賴1)mysql-devel: 確保版本大於5.1.40,直接從mysql官方網站下載對應版本wget -c http://cdn.mysql.com/Downloads/MySQL-5.5/MySQL-devel-5.5.35-1.rhel5.x86_64.rpm wget -c http://cdn.m