1.用C++编写的小游戏源代码
2.求发一个大智慧KTP源代码,谢谢
3.3d稀疏卷积——spconv源码剖析(三)
用C++编写的小游戏源代码
五子棋的代码:#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
using namespace std;
const int N=; //*的棋盘
const char ChessBoardflag = ' '; //棋盘标志
const char flag1='o'; //玩家1或电脑的棋子标志
const char flag2='X'; //玩家2的棋子标志
typedef struct Coordinate //坐标类
{
int x; //代表行
int y; //代表列
}Coordinate;
class GoBang //五子棋类
{
public:
GoBang() //初始化
{
InitChessBoard();
}
void Play() //下棋
{
Coordinate Pos1; // 玩家1或电脑
Coordinate Pos2; //玩家2
int n = 0;
while (1)
{
int mode = ChoiceMode();
while (1)
{
if (mode == 1) //电脑vs玩家
{
ComputerChess(Pos1,flag1); // 电脑下棋
if (GetVictory(Pos1, 0, flag1) == 1) //0表示电脑,真表示获胜
break;
PlayChess(Pos2, 2, flag2); //玩家2下棋
if (GetVictory(Pos2, 2, flag2)) //2表示玩家2
break;
}
else //玩家1vs玩家2
{
PlayChess(Pos1, 1, flag1); // 玩家1下棋
if (GetVictory(Pos1, 1, flag1)) //1表示玩家1
break;
PlayChess(Pos2, 2, flag2); //玩家2下棋
if (GetVictory(Pos2, 2, flag2)) //2表示玩家2
break;
}
}
cout << "***再来一局***" << endl;
cout << "y or n :";
char c = 'y';
cin >> c;
if (c == 'n')
break;
}
}
protected:
int ChoiceMode() //选择模式
{
int i = 0;
system("cls"); //系统调用,清屏
InitChessBoard(); //重新初始化棋盘
cout << "***0、退出 1、电脑vs玩家 2、玩家vs玩家***" << endl;
while (1)
{
cout << "请选择:";
cin >> i;
if (i == 0) //选择0退出
exit(1);
if (i == 1 || i == 2)
return i;
cout << "输入不合法" << endl;
}
}
void InitChessBoard() //初始化棋盘
{
for (int i = 0; i < N + 1; ++i)
{
for (int j = 0; j < N + 1; ++j)
{
_ChessBoard[i][j] = ChessBoardflag;
}
}
}
void PrintChessBoard() //打印棋盘,vue源码思维这个函数可以自己调整
{
system("cls"); //系统调用,清空屏幕
for (int i = 0; i < N+1; ++i)
{
for (int j = 0; j < N+1; ++j)
{
if (i == 0) //打印列数字
{
if (j!=0)
printf("%d ", j);
else
printf(" ");
}
else if (j == 0) //打印行数字
printf("%2d ", i);
else
{
if (i < N+1)
{
printf("%c |",_ChessBoard[i][j]);
}
}
}
cout << endl;
cout << " ";
for (int m = 0; m < N; m++)
{
printf("--|");
}
cout << endl;
}
}
void PlayChess(Coordinate& pos, int player, int flag) //玩家下棋
{
PrintChessBoard(); //打印棋盘
while (1)
{
printf("玩家%d输入坐标:", player);
cin >> pos.x >> pos.y;
if (JudgeValue(pos) == 1) //坐标合法
break;
cout << "坐标不合法,重新输入" << endl;
}
_ChessBoard[pos.x][pos.y] = flag;
}
void ComputerChess(Coordinate& pos, char flag) //电脑下棋
{
PrintChessBoard(); //打印棋盘
int x = 0;
int y = 0;
while (1)
{
x = (rand() % N) + 1; //产生1~N的随机数
srand((unsigned int) time(NULL));
y = (rand() % N) + 1; //产生1~N的随机数
srand((unsigned int) time(NULL));
if (_ChessBoard[x][y] == ChessBoardflag) //如果这个位置是空的,也就是没有棋子
break;
}
pos.x = x;
pos.y = y;
_ChessBoard[pos.x][pos.y] = flag;
}
int JudgeValue(const Coordinate& pos) //判断输入坐标是不是合法
{
if (pos.x > 0 && pos.x <= N&&pos.y > 0 && pos.y <= N)
{
if (_ChessBoard[pos.x][pos.y] == ChessBoardflag)
{
return 1; //合法
}
}
return 0; //非法
}
int JudgeVictory(Coordinate pos, char flag) //判断有没有人胜负(底层判断)
{
int begin = 0;
int end = 0;
int begin1 = 0;
int end1 = 0;
//判断行是否满足条件
(pos.y - 4) > 0 ? begin = (pos.y - 4) : begin = 1;
(pos.y + 4) >N ? end = N : end = (pos.y + 4);
for (int i = pos.x, j = begin; j + 4 <= end; j++)
{
if (_ChessBoard[i][j] == flag&&_ChessBoard[i][j + 1] == flag&&
_ChessBoard[i][j + 2] == flag&&_ChessBoard[i][j + 3] == flag&&
_ChessBoard[i][j + 4] == flag)
return 1;
}
//判断列是否满足条件
(pos.x - 4) > 0 ? begin = (pos.x - 4) : begin = 1;
(pos.x + 4) > N ? end = N : end = (pos.x + 4);
for (int j = pos.y, i = begin; i + 4 <= end; i++)
{
if (_ChessBoard[i][j] == flag&&_ChessBoard[i + 1][j] == flag&&
_ChessBoard[i + 2][j] == flag&&_ChessBoard[i + 3][j] == flag&&
_ChessBoard[i + 4][j] == flag)
return 1;
}
int len = 0;
//判断主对角线是否满足条件
pos.x > pos.y ? len = pos.y - 1 : len = pos.x - 1;
if (len > 4)
len = 4;
begin = pos.x - len; //横坐标的起始位置
begin1 = pos.y - len; //纵坐标的起始位置
pos.x > pos.y ? len = (N - pos.x) : len = (N - pos.y);
if (len>4)
len = 4;
end = pos.x + len; //横坐标的结束位置
end1 = pos.y + len; //纵坐标的结束位置
for (int i = begin, j = begin1; (i + 4 <= end) && (j + 4 <= end1); ++i, ++j)
{
if (_ChessBoard[i][j] == flag&&_ChessBoard[i + 1][j + 1] == flag&&
_ChessBoard[i + 2][j + 2] == flag&&_ChessBoard[i + 3][j + 3] == flag&&
_ChessBoard[i + 4][j + 4] == flag)
return 1;
}
//判断副对角线是否满足条件
(pos.x - 1) >(N - pos.y) ? len = (N - pos.y) : len = pos.x - 1;
if (len > 4)
len = 4;
begin = pos.x - len; //横坐标的起始位置
begin1 = pos.y + len; //纵坐标的起始位置
(N - pos.x) > (pos.y - 1) ? len = (pos.y - 1) : len = (N - pos.x);
if (len>4)
len = 4;
end = pos.x + len; //横坐标的结束位置
end1 = pos.y - len; //纵坐标的结束位置
for (int i = begin, j = begin1; (i + 4 <= end) && (j - 4 >= end1); ++i, --j)
{
if (_ChessBoard[i][j] == flag&&_ChessBoard[i + 1][j - 1] == flag&&
_ChessBoard[i + 2][j - 2] == flag&&_ChessBoard[i + 3][j - 3] == flag&&
_ChessBoard[i + 4][j - 4] == flag)
return 1;
}
for (int i = 1; i < N + 1; ++i) //棋盘有没有下满
{
for (int j =1; j < N + 1; ++j)
{
if (_ChessBoard[i][j] == ChessBoardflag)
return 0; //0表示棋盘没满
}
}
return -1; //和棋
}
bool GetVictory(Coordinate& pos, int player, int flag) //对JudgeVictory的一层封装,得到具体那个玩家获胜
{
int n = JudgeVictory(pos, flag); //判断有没有人获胜
if (n != 0) //有人获胜,0表示没有人获胜
{
PrintChessBoard();
if (n == 1) //有玩家赢棋
{
if (player == 0) //0表示电脑获胜,1表示玩家1,2表示玩家2
printf("***电脑获胜***\n");
else
printf("***恭喜玩家%d获胜***\n", player);
}
else
printf("***双方和棋***\n");
return true; //已经有人获胜
}
return false; //没有人获胜
}
private:
char _ChessBoard[N+1][N+1];
};
扩展资料:
设计思路
1、进行问题分析与设计,计划实现的功能为,开局选择人机或双人对战,确定之后比赛开始。饥荒源码分析
2、比赛结束后初始化棋盘,询问是否继续比赛或退出,后续可加入复盘、悔棋等功能。
3、整个过程中,涉及到了棋子和棋盘两种对象,努比亚社区源码同时要加上人机对弈时的AI对象,即涉及到三个对象。
求发一个大智慧KTP源代码,谢谢
大智慧顶底极品公式
实价线:(C-LLV(L,))/(HHV(H,)-LLV(L,))*,COLORWHITE;
A1:=(2*C+H+L)/4;
A2:=LLV(L,);
A3:=HHV(H,);
A4:=SMA((HHV(H,9)-C)/(HHV(H,9)-LLV(LOW,9))*-,9,1)+;
A5:=(C-LLV(L,9))/(HHV(H,9)- LLV(L,9))*;
A6:=SMA(SMA(A5,3,1),3,1)+;
A7:=A6-A4;
底部区域:IF(A7>,A7-,0),COLORYELLOW;
持有:STICKLINE(REF(底部区域,1)<底部区域,底部区域,REF(底部区域,1),5,0),COLORFFF0;
出货:STICKLINE(REF(底部区域,1)>底部区域,底部区域,REF(底部区域,1),5,0),COLORFF;
中线持有:EMA((A1-A2)/(A3-A2)*,),COLORBLUE;
中线出货:EMA(0.*REF(中线持有,1)+0.*中线持有,2),COLORRED;
STICKLINE(中线持有-中线出货>0,中线持有,中线出货,8,0),COLORBLUE;
STICKLINE(中线持有-中线出货<0,中线持有,中线出货,8,0),COLORRED;
绝密操盘
A:MA(CLOSE,3),ColorFFFF,LINETHICK0;
A1:=(CLOSE+HIGH+LOW)/(3);
B:=EMA(A1,);
B2:=REF(B,1);
MA:=EMA(CLOSE,);
DRAWTEXT((B>B2),ma,'*'),Colorffff;
DRAWTEXT((B<B2),ma,'*'),Coloryellow;
VAR1:=EMA(CLOSE,3);
VAR2:=EMA(CLOSE,8);
MA5:MA(CLOSE,5),Coloryellow;
MA:=EMA(CLOSE,);
STICKLINE(VAR1<MA,h,l,0,0),Colorgreen;
STICKLINE(VAR1<MA,c,o,8,0),Color;
STICKLINE(VAR1<MA,c,o,7,0),ColorE;
STICKLINE(VAR1<MA,c,o,6,0),Color;
STICKLINE(VAR1<MA,c,o,5,0),ColorA;
STICKLINE(VAR1<MA,c,o,4,0),ColorB;
STICKLINE(VAR1<MA,c,o,3,0),ColorC;
STICKLINE(VAR1<MA,c,o,2,0),ColorD;
STICKLINE(VAR1<MA,c,o,1,0),ColorE;
STICKLINE(VAR1>MA,h,l,0,0),Colorfff;
STICKLINE(VAR1>MA,c,o,8,0),Color;
STICKLINE(VAR1>MA,c,o,7,0),Color;
STICKLINE(VAR1>MA,c,o,6,0),ColorA2;
STICKLINE(VAR1>MA,c,o,5,0),ColorB3;
STICKLINE(VAR1>MA,c,o,4,0),ColorC8;
STICKLINE(VAR1>MA,c,o,3,0),ColorD7;
STICKLINE(VAR1>MA,c,o,2,0),ColorEA;
STICKLINE(VAR1>MA,c,o,1,0),ColorFF;
STICKLINE(VAR1<VAR2 AND VAR1>MA,h,l,0,0),Colorff5d;
STICKLINE(VAR1<VAR2 AND VAR1>MA,c,o,8,0),Colorff5d;
STICKLINE(VAR1<VAR2 AND VAR1>MA,c,o,5,0),Colorff;
STICKLINE(VAR1<VAR2 AND VAR1>MA,c,o,2,0),Colorff;
STICKLINE(VAR1>VAR2 AND VAR1<MA,h,l,0,0),Colorffff;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,8,0),Color8EE;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,7,0),Color9DD;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,6,0),ColorBB0;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,5,0),ColorCC6;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,4,0),ColorDD0;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,3,0),ColorEE6;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,2,0),ColorFF9;
STICKLINE(VAR1>VAR2 AND VAR1<MA,c,o,1,0),ColorFFFF;
MA2:=MA(CLOSE,);
MA:=MA(CLOSE,);
VARA:=((AMOUNT)/(VOL))/();
VARB:=((3)*(HIGH)+LOW+OPEN+(2)*(CLOSE))/(7);
VARC:=((SUM(AMOUNT,7))/(VARA))/();
VARD:=DMA(VARB,(VOL)/(VARC));
VARE:=((CLOSE-VARD)/(VARD))*();
VARF:=((CLOSE-LLV(LOW,))/(HHV(HIGH,)-LLV(LOW,)))*();
VARJ:=MA(VARE,)+STD(VARE,);
BIAS:=((CLOSE-MA(CLOSE,))/(MA(CLOSE,)))*();
K:=SMA(VARF,3,1);
顶:=(REF(BIAS,1)>=5) AND CROSS(VARJ,VARE) AND (K>);
DRAWTEXT((REF(BIAS,1)>=5) AND CROSS(VARJ,VARE) AND (K>),h*1.,'风险'),Coloryellow;
买了就赚
Var1:=(CLOSE+HIGH+LOW+OPEN)/4;
Var2:=SUMBARS(VOL,CAPITAL);
Var3:=HHV(Var1,Var2);
Var4:=LLV(Var1,Var2);
Var5:=(2*Var1-Var4-REF(Var4,1))/(Var3-Var4);
Var6:=(Var1-Var4)/(Var3-Var4);
Var7:=IF(Var1<=Var4,Var5*,Var6*);
Var8:=*(EMA(CLOSE,3)-EMA(LOW,))/EMA(LOW,);
Var9:=EMA(Var8,7);
VarA:=(WINNER(*CLOSE/)-WINNER(*CLOSE/))*;
VarB:=(-)*(WINNER(*CLOSE/)-WINNER(*CLOSE/))+5;
波段买入: IF(VarA+VarB<7 AND CROSS(Var8,Var9) AND Var9<- AND Var9<VarB,,),coloryellow , ;
DRAWICON(波段买入=,,1),colorred;
VarC:=HHV(HIGH,9)-LLV(LOW,9);
VarD:=HHV(HIGH,9)-CLOSE;
VarE:=CLOSE-LLV(LOW,9);
VarF:=VarD/VarC*-;
Var:=(CLOSE-LLV(LOW,))/(HHV(HIGH,)-LLV(LOW,))*;
Var:=(2*CLOSE+HIGH+LOW)/4;
Var:=SMA(VarE/VarC*,3,1);
Var:=LLV(LOW,);
Var:=SMA(Var,3,1)-SMA(VarF,9,1);
Var:=IF(Var>,Var-,0);
Var:=HHV(HIGH,);
Var:EMA((Var-Var)/(Var-Var)*,8);
巫修全制: Var, ,coloryellow ;
Var:=EMA(Var,5);
STICKLINE(Var>0 AND Var-Var>=0,,,6,0), ,colorred ;
STICKLINE(Var>0 AND Var-Var<0,,,6,1), ,colorff ;
STICKLINE(Var>0 AND Var-Var>=0,,,6,0),colorred, ;
STICKLINE(Var>0 AND Var-Var<0,,,6,1), ,colorff ;
STICKLINE(Var-Var>0,Var,Var,8,1), ,colorred ;
STICKLINE(Var-Var<0,Var,Var,8,1), ,colorff ;
Var:=REF(LOW,1);
Var:=SMA(ABS(LOW-Var),3,1)/SMA(MAX(LOW-Var,0),3,1)*;
Var:=EMA(IF(CLOSE*1.3,Var*,Var/),3);
Var:=LLV(LOW,);
Var:=HHV(Var,);
Var:=IF(MA(CLOSE,),1,0);
Var:=EMA(IF(LOW<=Var,(Var+Var*2)/2,0),3)/*Var;
Var:=IF(Var>,,Var);
STICKLINE(Var>-,0,Var,3,0), , colorffff;
底部吸筹指标: (CLOSE-MA(CLOSE,))/MA(CLOSE,)*, , colorff;
STICKLINE(CROSS(底部吸筹指标,-),,0,6,0), , colorffffff;
先知: (CLOSE-MA(CLOSE,5))/MA(CLOSE,5)*, , colorffff;
可能放量拉升: IF(CROSS(底部吸筹指标,-),1,0), , colorffffff;
Vark1:=(CLOSE-LLV(LOW,))/(HHV(HIGH,)-LLV(LOW,))*;
Vark2:=REVERSE(Vark1);
Vark3:=SMA(Vark1,3,1);
波段王:=SMA(Vark3,3,1), , COLORRED,linethick2;
波段鬼:=SMA(波段王,2.5,1),coloryellow,linethick2;
趋势线: 3*SMA((CLOSE-LLV(LOW,))/(HHV(HIGH,)-LLV(LOW,))*,5,1)-2*SMA(SMA((CLOSE-LLV(LOW,))/(HHV(HIGH,)-LLV(LOW,))*,5,1),3,1), ,COLORff,linethick2;
卖:IF((CROSS(波段鬼,波段王) or CROSS(波段鬼,趋势线) or CROSS(波段王,趋势线) ) AND 波段鬼>,,0),stick, ,colorffff ,linethick3;
RSV9:=(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*;
K1:=SMA(RSV9,3,1);
DK1:=K1-REF(K1,1),COLORSTICK;
出手就赢:IF(DK1>7 AND REF(DK1,1)<0 AND (DK1-REF(DK1,1))>9,,0), STICK,COLORyellow;
DRAWICON(出手就赢>0, ,1);
买点准备:IF(趋势线<=,0,), colorff,linethick3;
STICKLINE( CROSS(趋势线,),0,,6,0), COLORff,;
DRAWTEXT(IF(CROSS(趋势线,),,0),,'抄底'),COLORWHITE ;
DRAWTEXT(IF(CROSS(,趋势线),1,0), ,'$备钱'),COLORffcc,;
{ 目前位置:
对当前股票所处的技术位置进行评价,可对是否介入作出辅助判断}
RSV:=(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*;
K:=SMA(RSV,3,1);
D:=SMA(K,3,1);
J:=3*K-2*D;
DRAWTEXT(REF(J,1)<0 AND J>0,,'短买'),colorred ;
短线获利:STICKLINE(REF(J,1)<0 AND J>0,,0,2,0),colorff;
目前位置:K;
技术低位:;
技术中位:,POINTDOT;
技术高位:;
{ 红买绿卖 n:1 9 m1:1 3 m2:1 3 m3:1 5}
RSV:= (CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*;
FASTK:=SMA(RSV,M1,1);
K:SMA(FASTK,M2,1);
D:SMA(K,M3,1),colorwhite;
A1:=LLV(low,);
A2:=HHV(high,);
A3:=/(A2-A1);
,pointdot,linethick2;
,pointdot,linethick2;
VAR1:=HHV(HIGH,9)-LLV(LOW,9);
VAR2:=HHV(HIGH,9)-CLOSE;
VAR3:=CLOSE-LLV(LOW,9);
VAR4:=VAR2/VAR1*-;
VAR5:=(CLOSE-LLV(LOW,))/(HHV(HIGH,)-LLV(LOW,))*;
VAR6:=(2*CLOSE+HIGH+LOW)/4;
VAR7:=SMA(VAR3/VAR1*,3,1);
VAR8:=LLV(LOW,);
VAR9:=SMA(VAR7,3,1)-SMA(VAR4,9,1);
VAR:=IF(VAR9>,VAR9-,0);
VAR:=HHV(HIGH,);
VAR:=EMA((VAR6-VAR8)/(VAR-VAR8)*,);
VAR:=EMA(0.*REF(VAR,1)+0.*VAR,2);
VAR:=SMA(MAX(CLOSE-REF(CLOSE,1),0)/CLOSE,8,1)/SMA(ABS(INDEXC-REF
(INDEXC,1))/INDEXC,8,1)*-;
VAR:=MA(Var,3);
VAR:=REF(VAR,1);
STICKLINE(VAR-VAR>0,VAR,VAR,8,0),COLORRED;
STICKLINE(VAR-VAR<0,VAR,VAR,8,0),COLORgreen;
生命线:=EMA(VAR,5);
STICKLINE(cross(VAR,VAR) and VAR>,,,8,0),COLORff;
绿灯亮卖:0,colorff;
STICKLINE(cross(VAR,VAR) and VAR>VAR and VAR<,,0,8,0),COLORRED;
红灯亮买:0,colorred;
Var:=INDEXC;
Var:=MA(Var,6);
Var:=MA(Var,);
Var:=MA(Var,);
Var:=MA(Var,);
Var:=MA(Var,);
Var:=Var<REF(Var,1) AND Var<REF(Var,1) AND Var<Var*0.;
Var:=Var>Var*1. AND Var>Var*1.;
Var:=Var>Var*0.;
抄底A:= Var AND Var AND Var AND CLOSE/COST(8)<=0.8 AND CLOSE<OPEN;
{ 抄底1:}STICKLINE(抄底A,,,1,1),colorffff;
抄底1:0,colorffff;
Var2A:=CLOSE/MA(CLOSE,)*<;
Var2B:=CLOSE/MA(CLOSE,)*<;
Var2C:=HIGH>LOW*1.;
Var2D:=Var2C AND COUNT(Var2C,5)>1;
Var2E:=Var2D AND (Var2A OR Var2B);
Var2F:=DMA(EMA(CLOSE,),SUM(VOL,5)/3/CAPITAL);
Var:=(CLOSE-Var2F)/Var2F*+-(REF(HIGH,)/CLOSE-1.)*;
Var:=(CLOSE-REF(CLOSE,5))/CLOSE*<-9;
Var:=WINNER(CLOSE);
Var:=EMA((INDEXC-MA(INDEXC,))/INDEXC*,)<-4.9;
Var:=(MA(VOL,5)-VOL)/CAPITAL*<0.8;
Var:=(VOL-MA(VOL,))/VOL*;
抄底B:= Var AND Var AND Var<0. AND Var AND Var>;
{ 抄底2:}STICKLINE(抄底B,,,3,1),coloryellow;
抄底2:0,coloryellow;
Var:=(REF(CLOSE,1)+REF(CLOSE,2)+REF(CLOSE,3)+REF(CLOSE,4)+REF(CLOSE,5))/5;
Var:=(REF(CLOSE,2)+REF(CLOSE,3)+REF(CLOSE,4)+REF(CLOSE,5)+REF(CLOSE,6))/5;
Var:=(REF(CLOSE,3)+REF(CLOSE,4)+REF(CLOSE,5)+REF(CLOSE,6)+REF(CLOSE,7))/5;
Var:=(REF(CLOSE,4)+REF(CLOSE,5)+REF(CLOSE,6)+REF(CLOSE,7)+REF(CLOSE,8))/5;
Var3A:=(REF(CLOSE,5)+REF(CLOSE,6)+REF(CLOSE,7)+REF(CLOSE,8)+REF(CLOSE,9))/5;
BIAS3:=(CLOSE-MA(CLOSE,))/MA(CLOSE,)*;
抄底C:=(Var/CLOSE>1. OR Var/CLOSE>1. OR Var/CLOSE>1. OR Var/CLOSE>1. OR Var3A/CLOSE>1.) AND BIAS3<=- AND COST()/CLOSE>=1.5 AND CLOSE<OPEN;
{ 抄底3:}STICKLINE(抄底C,,,5,1),colorff;
抄底3:0,colorff;
Var3B:=(CLOSE-MA(CLOSE,))/MA(CLOSE,)*;
抄底D:= FILTER(IF(CROSS(Var3B,-),1,0),8);
{ 抄底4:}STICKLINE(CROSS(Var3B,-),,,8,1),colorwhite;
抄底4:0,colorwhite;
Var3C:=DMA(EMA(CLOSE,),SUM(VOL,5)/2/CAPITAL);
Var3D:=(CLOSE-Var3C)/Var3C*;
抄底E:= REF(Var3D,1)<- AND Var3D>REF(Var3D,1) AND REF(Var3D,1)<REF(Var3D,2) AND Var3D-REF(Var3D,1)>2.5;
{ 抄底5:}STICKLINE(抄底E,,,8,1),colorffcc;
抄底5:0,colorffcc;
Var3E:=*WINNER(REF(CLOSE,1)*1.1)-*WINNER(REF(CLOSE,1)*0.9);
抄底F:= CLOSE>OPEN*1. AND Var3E<;
{ 抄底6:}STICKLINE(抄底F,,,8,1),colorblue;
抄底6:0,colorblue;
3d稀疏卷积——spconv源码剖析(三)
构建Rulebook
下面看ops.get_indice_pairs,位于:spconv/ops.py
构建Rulebook由ops.get_indice_pairs接口完成
get_indice_pairs函数具体实现:
主要就是完成了一些参数的校验和预处理。首先,对于3d普通稀疏卷积,源码资本投根据输入shape大小,kernel size,stride等参数计算出输出输出shape,子流行稀疏卷积就不必计算了,输出shape和输入shape一样大小
准备好参数之后就进入最核心的get_indice_pairs函数。因为spconv通过torch.ops.load_library加载.so文件注册,所以这里通torch.ops.spconv.get_indice_pairs这种方式来调用该函数。
算子注册:在src/spconv/all.cc文件中通过Pytorch提供的OP Register(算子注册的方式)对底层c++ api进行了注册,可以python接口形式调用c++算子
同C++ extension方式一样,爱客服源码OP Register也是Pytorch提供的一种底层扩展算子注册的方式。注册的算子可以通过 torch.xxx或者 tensor.xxx的方式进行调用,该方式同样与pytorch源码解耦,增加和修改算子不需要重新编译pytorch源码。用该方式注册一个新的算子,流程非常简单:先编写C++相关的算子实现,然后通过pytorch底层的注册接口(torch::RegisterOperators),将该算子注册即可。
构建Rulebook实际通过python接口get_indice_pairs调用src/spconv/spconv_ops.cc文件种的getIndicePairs函数
代码位于:src/spconv/spconv_ops.cc
分析getIndicePairs直接将重心锁定在GPU逻辑部分,并且子流行3d稀疏卷积和正常3d稀疏卷积分开讨论,优先子流行3d稀疏卷积。
代码中最重要的3个变量分别为:indicePairs,indiceNum和gridOut,其建立过程如下:
indicePairs代表了稀疏卷积输入输出的映射规则,即Input Hash Table 和 Output Hash Table。这里分配理论最大的内存,它的shape为{ 2,kernelVolume,numAct},2表示输入和输出两个方向,kernelVolume为卷积核的volume size。例如一个3x3x3的卷积核,其volume size就是(3*3*3)。numAct表示输入有效(active)特征的数量。indiceNum用于保存卷积核每一个位置上的总的计算的次数,indiceNum对应中的count
代码中关于gpu建立rulebook调用create_submconv_indice_pair_cuda函数来完成,下面具体分析下create_submconv_indice_pair_cuda函数
子流线稀疏卷积
子流线稀疏卷积是调用create_submconv_indice_pair_cuda函数来构建rulebook
在create_submconv_indice_pair_cuda大可不必深究以下动态分发机制的运行原理。
直接将重心锁定在核函数:
prepareSubMGridKernel核函数中grid_size和block_size实则都是用的整形变量。其中block_size为tv::cuda::CUDA_NUM_THREADS,在include/tensorview/cuda_utils.h文件中定义,大小为。而grid_size大小通过tv::cuda::getBlocks(numActIn)计算得到,其中numActIn表示有效(active)输入数据的数量。
prepareSubMGridKernel作用:建立输出张量坐标(通过index表示)到输出序号之间的一张哈希表
见:include/spconv/indice.cu.h
这里计算index换了一种模板加递归的写法,看起来比较复杂而已。令:new_indicesIn = indicesIn.data(),可以推导得出index为:
ArrayIndexRowMajor位于include/tensorview/tensorview.h,其递归调用写法如下:
接着看核函数getSubMIndicePairsKernel3:
位于:include/spconv/indice.cu.h
看:
上述写法类似我们函数中常见的循环的写法,具体可以查看include/tensorview/kernel_utils.h
NumILP按默认值等于1的话,其stride也是gridDim.x*blockDim.x。索引最大值要小于该线程块的线程上限索引blockDim.x * gridDim.x,功能与下面代码类似:
参考: blog.csdn.net/ChuiGeDaQ...