当前位置: 首页 > 编程日记 > 正文

ucontext实现的用户级多线程框架3(实现echo服务器)

前面一篇文章实现了一个抢先式的用户级多线程框架,现在用那个框架编写一个echo服务,

因为只是个实验,所以代码写得比较杂乱,还有很多可能出错的情况也没有处理,这些在今后的进一

步研究中都会慢慢修改,下面是代码:

uthread.h

/*
* brief: 用ucontext实现的用户级线程框架
* author: kenny huang
* date: 2009/10/13
* email: huangweilook@21cn.com
*/
#ifndef _UTHREAD_H
#define _UTHREAD_H
#include <ucontext.h>
#include <stdio.h>
#include <string.h>
#include <list>
#include <pthread.h>
#include <signal.h>
#include "socketwrapper.h"

#define MAX_UTHREAD 128

void int_signal_handler(int sig);
//用户态线程的当前状态
enum thread_status
{
ACTIVED = 0,//可运行的
BLOCKED,//被阻塞
SLEEP,//主动休眠
DIE,//死死亡
};

typedef int (*uthread_func)(void*);

class Scheduler;
class u_thread;

typedef struct
{
int index;//在Scheduler::threads中的下标
u_thread *p_uthread;
ucontext_t *p_context;
}uthread_id;

/*
* 用户态线程
*/
class u_thread
{
friend class Scheduler;
private:
u_thread(unsigned int ssize,int index,uthread_id parent)
:ssize(ssize),_status(BLOCKED),parent_context(parent.p_context)
{
stack = new char[ssize];
ucontext.uc_stack.ss_sp = stack;
ucontext.uc_stack.ss_size = ssize;
getcontext(&ucontext);
uid.index = index;
uid.p_uthread = this;
uid.p_context = &ucontext;

}
~u_thread()
{
delete []stack;
}
static void star_routine(int uthread,int func,int arg);

public:
ucontext_t* GetParentContext()
{
return parent_context;
}
ucontext_t *GetContext()
{
return &ucontext;
}
void SetStatus(thread_status _status)
{
this->_status = _status;
}
thread_status GetStatus()
{
return _status;
}
uthread_id GetUid()
{
return uid;
}

private:
ucontext_t ucontext;
ucontext_t *parent_context;//父亲的context
char *stack;//coroutine使用的栈
unsigned int ssize;//栈的大小
thread_status _status;
uthread_id uid;
};

void BeginRun();
bool cSpawn(uthread_func func,void *arg,unsigned int stacksize);
int cRecv(int sock,char *buf,int len);
int cSend(int sock,char *buf,int len);
int cListen(int sock);
void cSleep(int t);

class beat;

/*
* 任务调度器
*/
class Scheduler
{
friend class beat;
friend class u_thread;
friend void BeginRun();
friend bool cSpawn(uthread_func func,void *arg,unsigned int stacksize);
friend int cRecv(int sock,char *buf,int len);
friend int cSend(int sock,char *buf,int len);
friend int cListen(int sock);
friend void cSleep(int t);
public:
static void scheduler_init();
static void int_sig();



private:

//休眠time时间
static void sleep(int t);
static void check_Network();
static void schedule();
static bool spawn(uthread_func func,void *arg,unsigned int stacksize);
static int recv(int sock,char *buf,int len);
static int send(int sock,char *buf,int len);
static int listen(int sock);

private:
static std::list<u_thread*> activeList;//可运行uthread列表

static std::list<std::pair<u_thread*,time_t> > sleepList;//正在睡眠uthread列表
static volatile bool block_signal;
static char stack[4096];

static ucontext_t ucontext;//Scheduler的context

static uthread_id uid_current;//当前正获得运行权的context

static uthread_id uid_self;

static u_thread *threads[MAX_UTHREAD];
static int total_count;
static int epollfd;
const static int maxsize = 10;
};
/*心跳发射器,发射器必须运行在一个独立的线程中,以固定的间隔
* 往所有运行着coroutine的线程发送中断信号
*/
class beat
{
public:
beat(unsigned int interval):interval(interval)
{}
void setThread(pthread_t id)
{
thread_scheduler = id;
}
void loop()
{
while(true)
{
//每隔固定时间向所有线程发中断信号
::usleep(1000 * interval);
while(1)
{
if(!Scheduler::block_signal)
{
pthread_kill(thread_scheduler,SIGUSR1);
break;
}
}

}
}
private:
unsigned int interval;//发送中断的间隔(豪秒)
pthread_t thread_scheduler;
};


bool initcoroutine(unsigned int interval);


#endif

uthread.cpp

#include "uthread.h"
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/epoll.h>
#include "thread.h"

ucontext_t Scheduler::ucontext;

char Scheduler::stack[4096];

uthread_id Scheduler::uid_current;

uthread_id Scheduler::uid_self;

u_thread *Scheduler::threads[MAX_UTHREAD];

int Scheduler::total_count = 0;

int Scheduler::epollfd = 0;

volatile bool Scheduler::block_signal = true;

std::list<u_thread*> Scheduler::activeList;

std::list<std::pair<u_thread*,time_t> > Scheduler::sleepList;

struct sock_struct
{
int sockfd;
u_thread *uThread;
};

void int_signal_handler(int sig)
{
Scheduler::int_sig();
}

void u_thread::star_routine(int uthread,int func,int arg)
{
u_thread *self_uthread = (u_thread *)uthread;
assert(self_uthread);

self_uthread->SetStatus(ACTIVED);
ucontext_t *self_context = self_uthread->GetContext();
swapcontext(self_context,self_uthread->GetParentContext());
Scheduler::block_signal = false;

uthread_func _func = (uthread_func)func;
void *_arg = (void*)arg;
int ret = _func(_arg);
self_uthread->SetStatus(DIE);
}
void Scheduler::scheduler_init()
{
for(int i = 0; i < MAX_UTHREAD; ++i)
threads[i] = 0;
getcontext(&ucontext);
ucontext.uc_stack.ss_sp = stack;
ucontext.uc_stack.ss_size = sizeof(stack);
ucontext.uc_link = NULL;

//scheduler占用下标0
makecontext(&ucontext,schedule, 0);

uid_self.index = 0;
uid_self.p_uthread = 0;
uid_self.p_context = &ucontext;
uid_current = uid_self;

}
int Scheduler::listen(int sock)
{
u_thread *self_thread = uid_current.p_uthread;

epoll_event ev;
sock_struct *ss = new sock_struct;
ss->uThread = self_thread;
ss->sockfd = sock;
ev.data.ptr = (void*)ss;
ev.events = EPOLLIN;
int ret;
TEMP_FAILURE_RETRY(ret = epoll_ctl(epollfd,EPOLL_CTL_ADD,sock,&ev));
if(ret != 0)
{
return -1;
}

self_thread->SetStatus(BLOCKED);
Scheduler::block_signal = true;
swapcontext(uid_current.p_context,&Scheduler::ucontext);
Scheduler::block_signal = false;
return 1;
}

int Scheduler::recv(int sock,char *buf,int len)
{
if(!buf || !(len > 0))
return -1;
u_thread *self_thread = uid_current.p_uthread;
sock_struct *ss = new sock_struct;
ss->uThread = self_thread;
ss->sockfd = sock;
epoll_event ev;
ev.data.ptr = (void*)ss;
ev.events = EPOLLIN;
int ret;
TEMP_FAILURE_RETRY(ret = epoll_ctl(epollfd,EPOLL_CTL_ADD,sock,&ev));
if(ret != 0)
return -1;

self_thread->SetStatus(BLOCKED);
Scheduler::block_signal = true;
swapcontext(uid_current.p_context,&Scheduler::ucontext);
printf("recv return/n");
Scheduler::block_signal = false;
ret = read(sock,buf,len);
return ret;
}
int Scheduler::send(int sock,char *buf,int len)
{
if(!buf || !(len > 0))
return -1;

u_thread *self_thread = uid_current.p_uthread;

sock_struct *ss = new sock_struct;
ss->uThread = self_thread;
ss->sockfd = sock;
epoll_event ev;
ev.data.ptr = (void*)ss;
ev.events = EPOLLOUT;
int ret;
TEMP_FAILURE_RETRY(ret = epoll_ctl(epollfd,EPOLL_CTL_ADD,sock,&ev));
if(ret != 0)
return -1;
self_thread->SetStatus(BLOCKED);
Scheduler::block_signal = true;
swapcontext(uid_current.p_context,&Scheduler::ucontext);
Scheduler::block_signal = false;
ret = write(sock,buf,len);
return ret;
}
void Scheduler::check_Network()
{
epoll_event events[maxsize];
sock_struct *ss;
int nfds = TEMP_FAILURE_RETRY(epoll_wait(epollfd,events,maxsize,0));
for( int i = 0 ; i < nfds ; ++i)
{
//套接口可读
if(events[i].events & EPOLLIN)
{
ss = (sock_struct*)events[i].data.ptr;
printf("a sock can read/n");
ss->uThread->SetStatus(ACTIVED);
epoll_event ev;
ev.data.fd = ss->sockfd;
if(0 != TEMP_FAILURE_RETRY(epoll_ctl(epollfd,EPOLL_CTL_DEL,ev.data.fd,&ev)))
{
printf("error here/n");
exit(0);
}
delete ss;
continue;
}
//套接口可写
if(events[i].events & EPOLLOUT)
{
ss = (sock_struct*)events[i].data.ptr;
printf("a sock can write/n");
ss->uThread->SetStatus(ACTIVED);
epoll_event ev;
ev.data.fd = ss->sockfd;
TEMP_FAILURE_RETRY(epoll_ctl(epollfd,EPOLL_CTL_DEL,ev.data.fd,&ev));
delete ss;
continue;
}
}
}
void Scheduler::schedule()
{
epollfd = TEMP_FAILURE_RETRY(epoll_create(maxsize));

if(epollfd<= 0)
{
printf("epoll init error/n");
return;
}

while(total_count > 0)
{

//首先执行active列表中的uthread
std::list<u_thread*>::iterator it = activeList.begin();
std::list<u_thread*>::iterator end = activeList.end();
for( ; it != end; ++it)
{
if(*it && (*it)->GetStatus() == ACTIVED)
{
uid_current = (*it)->GetUid();
swapcontext(&ucontext,uid_current.p_context);
uid_current = uid_self;

int index = (*it)->GetUid().index;
if((*it)->GetStatus() == DIE)
{
printf("%d die/n",index);
delete threads[index];
threads[index] = 0;
--total_count;
activeList.erase(it);
break;
}
else if((*it)->GetStatus() == SLEEP)
{
printf("%d sleep/n",index);
activeList.erase(it);
break;
}
}
}
//检查网络,看看是否有套接口可以操作
check_Network();
//看看Sleep列表中是否有uthread该醒来了
std::list<std::pair<u_thread*,time_t> >::iterator its = sleepList.begin();
std::list<std::pair<u_thread*,time_t> >::iterator ends = sleepList.end();
time_t now = time(NULL);
for( ; its != ends; ++its)
{
//可以醒来了
if(now >= its->second)
{
u_thread *uthread = its->first;
uthread->SetStatus(ACTIVED);
activeList.push_back(uthread);
sleepList.erase(its);
break;
}
}
}
printf("scheduler end/n");
}

bool Scheduler::spawn(uthread_func func,void *arg,unsigned int stacksize)
{
printf("uthread_create/n");
if(total_count >= MAX_UTHREAD)
return false;
int i = 1;
for( ; i < MAX_UTHREAD; ++i)
{
if(threads[i] == 0)
{
threads[i] = new u_thread(stacksize,i,uid_current);
++total_count;
ucontext_t *cur_context = threads[i]->GetContext();
activeList.push_back(threads[i]);

cur_context->uc_link = &ucontext;
makecontext(cur_context,(void (*)())u_thread::star_routine, 3,(int)&(*threads[i]),(int)func,(int)arg);
swapcontext(uid_current.p_context, cur_context);
printf("return from parent/n");
return true;
}
}

return false;
}
void Scheduler::sleep(int t)
{
u_thread *self_thread = uid_current.p_uthread;

time_t now = time(NULL);
now += t;
//插入到sleep列表中
sleepList.push_back(std::make_pair(self_thread,now));

//保存当前上下文切换回scheduler
self_thread->SetStatus(SLEEP);

ucontext_t *cur_context = self_thread->GetContext();
Scheduler::block_signal = true;
swapcontext(cur_context,&Scheduler::ucontext);
Scheduler::block_signal = false;
}
void Scheduler::int_sig()
{
//printf("Scheduler::int_sig()%x/n",uid_current.p_context);
Scheduler::block_signal = true;
swapcontext(uid_current.p_context,&Scheduler::ucontext);
Scheduler::block_signal = false;
}

class HeartBeat : public runnable
{
public:
HeartBeat(unsigned int interval)
{
_beat = new beat(interval);
_beat->setThread(pthread_self());
}

~HeartBeat()
{
delete _beat;
}

bool run()
{
_beat->loop();
return true;
}

private:
beat *_beat;
};

bool initcoroutine(unsigned int interval)
{
//初始化信号
struct sigaction sigusr1;
sigusr1.sa_flags = 0;
sigusr1.sa_handler = int_signal_handler;
sigemptyset(&sigusr1.sa_mask);
int status = sigaction(SIGUSR1,&sigusr1,NULL);
if(status == -1)
{
printf("error sigaction/n");
return false;
}

//首先初始化调度器
Scheduler::scheduler_init();


//启动心跳
static HeartBeat hb(interval);
static Thread c(&hb);
c.start();
return true;
}

void BeginRun()
{
Scheduler::schedule();
}

bool cSpawn(uthread_func func,void *arg,unsigned int stacksize)
{
return Scheduler::spawn(func,arg,stacksize);
}

int cRecv(int sock,char *buf,int len)
{
return Scheduler::recv(sock,buf,len);
}

int cSend(int sock,char *buf,int len)
{
return Scheduler::send(sock,buf,len);
}

int cListen(int sock)
{
return Scheduler::listen(sock);
}

void cSleep(int t)
{
return Scheduler::sleep(t);
}

echoserver.c

// kcoroutine.cpp : 定义控制台应用程序的入口点。
//
#include "uthread.h"
#include "thread.h"
int port;
int test(void *arg)
{
char *name = (char*)arg;
unsigned long c = 0;
while(1)
{
if(c % 10000 == 0)
{
printf("%d/n",c);
cSleep(1);
}
++c;
}
}
int echo(void *arg)
{
int sock = *(int*)arg;
while(1)
{
char buf[1024];
int ret = cRecv(sock,buf,1024);
if(ret > 0)
{
printf("%s/n",buf);
ret = cSend(sock,buf,ret);
}
}
}
int listener(void *arg)
{
struct sockaddr_in servaddr;
int listenfd;
if(0 > (listenfd = Tcp_Listen("127.0.0.1",port,servaddr,5)))
{
printf("listen error/n");
return 0;
}
while(1)
{
if(cListen(listenfd) > 0)
{
printf("a user comming/n");
struct sockaddr_in cliaddr;
socklen_t len;
int sock = Accept(listenfd,(struct sockaddr*)NULL,NULL);
if(sock >= 0)
{
cSpawn(echo,&sock,4096);
}

}
}
}
int main(int argc, char **argv)
{
port = atoi(argv[1]);
if(!initcoroutine(20))
return 0;
cSpawn(listener,0,4096);
char name[10] = "test";
cSpawn(test,name,4096);

printf("create finish/n");

//开始调度线程的运行
BeginRun();
return 0;
}

运行后会看到控制台中不断的输出1,那是runable_test在工作,

telnet几个客户端上去,就可以看到echo的效果了,总体来看效果还不错,

不过context的切换效率还没有测试过.





转载于:https://www.cnblogs.com/sniperHW/archive/2012/04/02/2429644.html

相关文章:

asp.net 2.0中用GRIDVIEW插入新记录

出处&#xff1a;www.knowsky.com 作者&#xff1a;www.knowsky.com <script languageJavaScript src"/ad/ad.js"></script> name"mq" marginwidth"0" marginheight"0" src"../../ad.html" frameborder"no…

我在攻克机器学习硕士学位的那些年

编者按&#xff1a;人工智能发展日趋成熟&#xff0c;也成为众多开发者职业生涯的首选方向。然而相较于其他领域&#xff0c;人工智能中的深度学习、机器学习、计算视觉、神经网络等技术更为错综复杂&#xff0c;进修难度也更胜一筹。对此&#xff0c;对于入门和想要进阶的学生…

POJ 3174 暴力枚举

思路&#xff1a; 暴力枚举三个点 判一判 搞定 &#xff08;x1*y1x2*y2&#xff09; x1、y1、x2、y2为他们两两的差 //By SiriusRen #include <cstdio> using namespace std; int n,cnt; struct Point{int x,y;}point[888]; struct ans{int x,y,z;}ans[888]; int main…

TensorFlow、PyTorch夹缝之下:后浪的进击和野望

作者 | Just出品 | AI科技大本营&#xff08;rgznai100&#xff09;“我发现&#xff0c;软件研发总会延期。”一流科技CEO袁进辉说。按照他的预期&#xff0c;深度学习框架OneFlow做两年就能开源给开发者检验&#xff0c;但时间向后延长了近一年半&#xff0c;“确实预计的不准…

在Win 2003中配置ASP.net环境

作者&#xff1a;未知大家知道&#xff0c;Microsoft为了更好地预防恶意用户和攻击者的攻击&#xff0c;在默认情况下&#xff0c;没有将 IIS6.0 安装到 Windows Server 2003 家族的成员上。而且&#xff0c;当我们最初安装 IIS6.0 时&#xff0c;该服务在高度安全和"锁定…

网页中的数学公式

无意中发现一个在网页中显示数学公式的解决方案,MathJax&#xff0c;太崇拜这些人了&#xff01;他们才是真正地IT人&#xff0c;哪像国内我们这些民工&#xff1f; 代码如下&#xff1a; <!DOCTYPE html><html><head><title>MathJax AsciiMath Test P…

php删除目录下的所有文件和目录

<?php /*** 递归实现删除目录下的所有的文件和文件夹* param $dir 要删除的目录* param bool $deleteRootToo 是否删除根目录 默认不删除http://www.manongjc.com/article/1333.html*/ function unlinkRecursive($dir, $deleteRootToo false) {if(!$dh opendir($dir)){re…

DZX2无法读取会员短消息

我们在升级Discuz论坛时&#xff0c;如果没升级好&#xff0c;可能会出现各种各样的问题。比如登陆会员&#xff0c;但点“短消息”会出现错误&#xff0c;如下&#xff1a;提示&#xff1a;UCenter info: MySQL Query ErrorSQL:SELECT COUNT(*) FROM [Table]pm_members m WHER…

ASP.NET 如何操作文件

本文由chenyangasp版权所有&#xff0c;可以转载&#xff0c;复制&#xff0c;粘贴&#xff0c;并请注明出处&#xff0c;但不得修改&#xff01; 在asp.net操作文件的所有concept都在system.io namespace中&#xff0c;这个namespace包含读写操作文件所必需的类。 本文将详细…

摊牌了:我就靠这几点,搞定了算法面试官

很多时候&#xff0c;你即使提前复习了这些最常见的面试算法题&#xff0c;你依旧无法通过算法面试&#xff01;为什么&#xff1f;1. 你在提前准备复习的时候&#xff0c;在网上找了半天相应题目的分析文章&#xff0c;但你看了就是不懂。2. 你在面试的时候&#xff0c;卡壳了…

Spoooooky CSS 选择器

2019独角兽企业重金招聘Python工程师标准>>> 让我们今年有一些万圣节主题的帖子精神&#xff01;我会从超过 GRAVE.eR.CSS选择器中挑选一些将冻结你骨头的选择器。也许不可能&#xff0c;但他们至少有点怪异。 迟钝的猫头鹰选择器&#xff08;the lobotomized owl s…

关于无法创建aps.web项目的解决办法

出处&#xff1a;CSDN 作者&#xff1a;ahking <script languageJavaScript src"/ad/ad.js"></script> 1、当站点主目录没有创建应用程序&#xff1a; 通过FP扩展虚拟目录的方式来建立WEBAPP,步骤如下&#xff1a; &#xff08;1&#xff09;、右击站…

国内ntp时间服务器ip地址

NTP&#xff08;Network Time Protocol&#xff09;是由美国德拉瓦大学的David L. Mills教授于1985年提出&#xff0c;除了可以估算封包在网络上的往返延迟外&#xff0c;还可独立地估算计算机时钟偏差&#xff0c;从而实现在网络上的高精准度计算机校时&#xff0c;它是设计用…

谷歌顶级量子科学家详述他为何从谷歌辞职

加州大学圣塔芭芭拉分校&#xff08;UCSB&#xff09;的教授John Martinis作者 | Paul Smith-Goodson译者 | 天道酬勤&#xff0c;责编 | Carol 约翰马丁尼斯&#xff08;John Martinis&#xff09;教授从Google辞职的消息在整个量子学界引起了轩然大波。消息宣布几天后&#x…

论文笔记之:Generative Adversarial Text to Image Synthesis

Generative Adversarial Text to Image Synthesis ICML 2016 摘要&#xff1a;本文将文本和图像练习起来&#xff0c;根据文本生成图像&#xff0c;结合 CNN 和 GAN 来有效的进行无监督学习。 Attribute Representation: 是一个非常具有意思的方向。由图像到文本&#xff0c;可…

ADO.NET 2.0 中的架构

Bob BeaucheminDevelopMentor 适用于&#xff1a;Microsoft ADO.NET 2.0Microsoft Visual Studio 2005C# 编程语言 摘要&#xff1a;了解在 ADO.NET 中对于从您的数据源访问元数据的增强支持。下载相关的 SchemasSample.exe 示例代码。 本页内容 深入了解新的公共元数据 API究…

Android实现程序前后台切换效果

本文演示如何在Android中实现程序前后台切换效果。 在介绍程序实现之前&#xff0c;我们先看下Android中Activities和Task的基础知识。 我们都知道&#xff0c;一个Activity 可以启动另一个Activity,即使这个Activity是定义在别一个应用程序里的&#xff0c;比如说&#xff0c;…

如果特斯拉制造相机的梦想像激光雷达一样真正实现,它可能会帮助到更多同行...

这张来自伪激光雷达论文的图片显示了旧的黄色实点云作者 | Brad Templeton译者 | 天道酬勤&#xff0c;责编 | Carol特斯拉 CEO 埃隆马斯克&#xff08;Elon Musk&#xff09;对自动驾驶激光雷达&#xff08;3D图像技术&#xff09;的看法是众所周知的。他不打算在特斯拉里使用…

java分享第五天(数组)

1 声明数组变量&#xff1a; double[] mylist; or double mylist[]; 2 创建数组&#xff1a; 可以通过使用new运算符使用以下语法创建一个数组&#xff1a; arrayRefVarnew dataType[arraySize]; 上面的语句做了两件事&#xff1a; 它创建一个数据使用new dataType[…

效率!效率!效率!

原著&#xff1a;Mark Davis 翻译&#xff1a;onefi 2004年4月21日 摘要&#xff1a; 此篇文章包括了一些在网页设计中时常用到的脚本。我们可以清晰的体会到其中的执行速度。这将有助于提高您的动态网页的速度。 导言&#xff1a; 自从有了IE4.0以后&#xff0c;我们所看到的…

Android UI Button 和GridView 的设计--优化(2)

Android 按钮的UI设计&#xff0c;ListView 以及GridView的UI设计 一.按钮的状态 我们一般搞UI设计,按钮通常有三个状态&#xff1a;normal(正常状态);focus(焦点状态),pressed(按下状态)。如下图所示: 我们会在res/drawable目录下定义一个资源文件&#xff0c;比如我们本例中要…

玩转社区开源贡献,看这篇就够了!

来源 | TensorFlow本文来自社区投稿与征集。作者唐源&#xff0c;现任蚂蚁集团技术专家&#xff0c;目前专注于建立 AI 基础架构和自动机器学习平台。本文转自&#xff1a;https://zhuanlan.zhihu.com/p/165098355作为最早一批非谷歌的 TensorFlow 社区贡献者&#xff0c;同时也…

grub2 命令行进入系统

有时候grub引导可能出问题&#xff0c;因此我们需要在grub界面利用命令行进入系统。下边就做一个简单的介绍。1、在grub界面&#xff0c;按c进入命令行界面2、命令行输入“ grub>set root(hd ”之后按tab键&#xff0c;查看你的硬盘&#xff0c;hd0表示第一块硬盘&#xf…

梯度中心化,一行代码加速训练并提升泛化能力

来源 | 晓飞的算法工程笔记优化器(Optimizer)对于深度神经网络在大型数据集上的训练是十分重要的&#xff0c;如SGD和SGDM&#xff0c;优化器的目标有两个&#xff1a;加速训练过程和提高模型的泛化能力。目前&#xff0c;很多工作研究如何提高如SGD等优化器的性能&#xff0c;…

Microsoft程序员测试题

原创&#xff1a;onefi http://www.frontfree.net/2003年6月1日 最近大家在网站上看到不少Microsoft的测试题&#xff0c;引来不少的眼光。我在这里把所有的测试题加以整理&#xff0c;再附上自己的答案。&#xff08;个别题目答案有多种&#xff0c;文本仅代表作者的思路&a…

裸centos安装PCRE时报错解决

2019独角兽企业重金招聘Python工程师标准>>> no acceptable C compiler found in $PATH由于没有gcc的编译环境引起的&#xff0c;yum install gcc就ok unrecognized option -DHAVE_CONFIG_H由于没有gcc-c的编译环境引起的&#xff0c;yum -y install gcc-c 转载于:…

mysql删除开放用户权限

来访用户ODBC 1,在本地的cmd中用root用户进入mysql2,创建一个ODBC的用户create user ODBClocalhost;查看用户是否创建成功select user,host from mysql.user;3,将所有的权限开放给ODBC用户grant all on *.* to ODBClocalhost;查看ODBC用户的权限show grants for ODBC localhost…

AI不止能美颜,美妆迁移这样做 | 赠书

本文内容节选自《深度学习之人脸图像处理&#xff1a;核心算法与案例实践》&#xff0c;作者言有三。美颜和美妆是人脸中很常见的技术&#xff0c;在网络直播以及平常的社交生活中都有很多应用场景。本文重点介绍的是人脸妆造迁移的核心技术及其相关资源。想要了解关于深度学习…

ASP.Net中自定义Http处理及应用之HttpModule篇

HttpHandler实现了类似于ISAPI Extention的功能&#xff0c;他处理请求(Request)的信息和发送响应(Response)。HttpHandler功能的实现通过实现IHttpHandler接口来达到。而HttpModule实现了类似于ISAPI Filter的功能。 HttpModule的实现HttpModules实现了类似于ISAPI Filter的功…

未处理的异常导致基于 ASP.NET 的应用程序意外退出

问题具体见&#xff1a;http://q.cnblogs.com/q/34874/ 相应站点的w3wp.exe 会意外终止 EventLog中的信息&#xff1a; An unhandled exception occurred and the process was terminated. Application ID: DefaultDomain Process ID: 43644 Exception: System.Runtime.Seri…