nvGRAPH API参考分析(二)

nvGRAPH Code Examples

本文提供了简单的示例。

1. nvGRAPH convert topology example

void check(nvgraphStatus_t status) {

if (status != NVGRAPH_STATUS_SUCCESS) {

printf("ERROR : %d\n",status);

exit(0);

}

}

int main(int argc, char **argv) {

size_t  n = 6, nnz = 10;

// nvgraph variables

nvgraphHandle_t handle;

nvgraphCSCTopology32I_t CSC_input;

nvgraphCSRTopology32I_t CSR_output;

float *src_weights_d, *dst_weights_d;

cudaDataType_t edge_dimT = CUDA_R_32F;

// Allocate source data

CSC_input = (nvgraphCSCTopology32I_t) malloc(sizeof(struct nvgraphCSCTopology32I_st));

CSC_input->nvertices = n; CSC_input->nedges = nnz;

cudaMalloc( (void**)&(CSC_input->destination_offsets), (n+1)*sizeof(int));

cudaMalloc( (void**)&(CSC_input->source_indices), nnz*sizeof(int));

cudaMalloc( (void**)&src_weights_d, nnz*sizeof(float));

// Copy source data

float src_weights_h[] = {0.333333f, 0.5f, 0.333333f, 0.5f, 0.5f, 1.0f, 0.333333f, 0.5f, 0.5f, 0.5f};

int destination_offsets_h[] = {0, 1, 3, 4, 6, 8, 10};

int source_indices_h[] = {2, 0, 2, 0, 4, 5, 2, 3, 3, 4};

cudaMemcpy(CSC_input->destination_offsets, destination_offsets_h, (n+1)*sizeof(int), cudaMemcpyDefault);

cudaMemcpy(CSC_input->source_indices, source_indices_h, nnz*sizeof(int), cudaMemcpyDefault);

cudaMemcpy(src_weights_d, src_weights_h, nnz*sizeof(float), cudaMemcpyDefault);

// Allocate destination data

CSR_output = (nvgraphCSRTopology32I_t) malloc(sizeof(struct nvgraphCSRTopology32I_st));

cudaMalloc( (void**)&(CSR_output->source_offsets), (n+1)*sizeof(int));

cudaMalloc( (void**)&(CSR_output->destination_indices), nnz*sizeof(int));

cudaMalloc( (void**)&dst_weights_d, nnz*sizeof(float));

// Starting nvgraph and convert

check(nvgraphCreate (&handle));

check(nvgraphConvertTopology(handle, NVGRAPH_CSC_32, CSC_input, src_weights_d,

&edge_dimT, NVGRAPH_CSR_32, CSR_output, dst_weights_d));

// Free memory

check(nvgraphDestroy(handle));

cudaFree(CSC_input->destination_offsets);

cudaFree(CSC_input->source_indices);

cudaFree(CSR_output->source_offsets);

cudaFree(CSR_output->destination_indices);

cudaFree(src_weights_d);

cudaFree(dst_weights_d);

free(CSC_input);

free(CSR_output);

return 0;

}

2. nvGRAPH convert graph example

void check(nvgraphStatus_t status) {

if (status != NVGRAPH_STATUS_SUCCESS) {

printf("ERROR : %d\n",status);

exit(0);

}

}

int main(int argc, char **argv) {

size_t  n = 6, nnz = 10, vert_sets = 2, edge_sets = 1;

// nvgraph variables

nvgraphHandle_t handle; nvgraphGraphDescr_t src_csc_graph;

nvgraphCSCTopology32I_t CSC_input;

cudaDataType_t edge_dimT = CUDA_R_32F;

cudaDataType_t* vertex_dimT;

// Allocate host data

float *pr_1 = (float*)malloc(n*sizeof(float));

void **vertex_dim = (void**)malloc(vert_sets*sizeof(void*));

vertex_dimT = (cudaDataType_t*)malloc(vert_sets*sizeof(cudaDataType_t));

CSC_input = (nvgraphCSCTopology32I_t) malloc(sizeof(struct nvgraphCSCTopology32I_st));

// Initialize host data

float weights_h[] = {0.333333f, 0.5f, 0.333333f, 0.5f, 0.5f, 1.0f, 0.333333f, 0.5f, 0.5f, 0.5f};

int destination_offsets_h[] = {0, 1, 3, 4, 6, 8, 10};

int source_indices_h[] = {2, 0, 2, 0, 4, 5, 2, 3, 3, 4};

float bookmark_h[] = {0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};

vertex_dim[0] = (void*)bookmark_h; vertex_dim[1]= (void*)pr_1;

vertex_dimT[0] = CUDA_R_32F; vertex_dimT[1]= CUDA_R_32F, vertex_dimT[2]= CUDA_R_32F;

// Starting nvgraph

check(nvgraphCreate (&handle));

check(nvgraphCreateGraphDescr (handle, &src_csc_graph));

CSC_input->nvertices = n; CSC_input->nedges = nnz;

CSC_input->destination_offsets = destination_offsets_h;

CSC_input->source_indices = source_indices_h;

// Set graph connectivity and properties (tranfers)

check(nvgraphSetGraphStructure(handle, src_csc_graph, (void*)CSC_input, NVGRAPH_CSC_32));

check(nvgraphAllocateVertexData(handle, src_csc_graph, vert_sets, vertex_dimT));

check(nvgraphAllocateEdgeData  (handle, src_csc_graph, edge_sets, &edge_dimT));

for (int i = 0; i < 2; ++i)

check(nvgraphSetVertexData(handle, src_csc_graph, vertex_dim[i], i));

check(nvgraphSetEdgeData(handle, src_csc_graph, (void*)weights_h, 0));

// Convert to CSR graph

nvgraphGraphDescr_t dst_csr_graph;

check(nvgraphCreateGraphDescr (handle, &dst_csr_graph));

check(nvgraphConvertGraph(handle, src_csc_graph, dst_csr_graph, NVGRAPH_CSR_32));

check(nvgraphDestroyGraphDescr(handle, src_csc_graph));

check(nvgraphDestroyGraphDescr(handle, dst_csr_graph));

check(nvgraphDestroy(handle));

free(pr_1); free(vertex_dim); free(vertex_dimT);

free(CSC_input);

return 0;

}

3. nvGRAPH pagerank example

void check(nvgraphStatus_t status) {

if (status != NVGRAPH_STATUS_SUCCESS) {

printf("ERROR : %d\n",status);

exit(0);

}

}

int main(int argc, char **argv) {

size_t  n = 6, nnz = 10, vert_sets = 2, edge_sets = 1;

float alpha1 = 0.9f; void *alpha1_p = (void *) &alpha1;

// nvgraph variables

nvgraphHandle_t handle; nvgraphGraphDescr_t graph;

nvgraphCSCTopology32I_t CSC_input;

cudaDataType_t edge_dimT = CUDA_R_32F;

cudaDataType_t* vertex_dimT;

// Allocate host data

float *pr_1 = (float*)malloc(n*sizeof(float));

void **vertex_dim = (void**)malloc(vert_sets*sizeof(void*));

vertex_dimT = (cudaDataType_t*)malloc(vert_sets*sizeof(cudaDataType_t));

CSC_input = (nvgraphCSCTopology32I_t) malloc(sizeof(struct nvgraphCSCTopology32I_st));

// Initialize host data

float weights_h[] = {0.333333f, 0.5f, 0.333333f, 0.5f, 0.5f, 1.0f, 0.333333f, 0.5f, 0.5f, 0.5f};

int destination_offsets_h[] = {0, 1, 3, 4, 6, 8, 10};

int source_indices_h[] = {2, 0, 2, 0, 4, 5, 2, 3, 3, 4};

float bookmark_h[] = {0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};

vertex_dim[0] = (void*)bookmark_h; vertex_dim[1]= (void*)pr_1;

vertex_dimT[0] = CUDA_R_32F; vertex_dimT[1]= CUDA_R_32F, vertex_dimT[2]= CUDA_R_32F;

// Starting nvgraph

check(nvgraphCreate (&handle));

check(nvgraphCreateGraphDescr (handle, &graph));

CSC_input->nvertices = n; CSC_input->nedges = nnz;

CSC_input->destination_offsets = destination_offsets_h;

CSC_input->source_indices = source_indices_h;

// Set graph connectivity and properties (tranfers)

check(nvgraphSetGraphStructure(handle, graph, (void*)CSC_input, NVGRAPH_CSC_32));

check(nvgraphAllocateVertexData(handle, graph, vert_sets, vertex_dimT));

check(nvgraphAllocateEdgeData  (handle, graph, edge_sets, &edge_dimT));

for (int i = 0; i < 2; ++i)

check(nvgraphSetVertexData(handle, graph, vertex_dim[i], i));

check(nvgraphSetEdgeData(handle, graph, (void*)weights_h, 0));

check(nvgraphPagerank(handle, graph, 0, alpha1_p, 0, 0, 1, 0.0f, 0));

// Get result

check(nvgraphGetVertexData(handle, graph, vertex_dim[1], 1));

check(nvgraphDestroyGraphDescr(handle, graph));

check(nvgraphDestroy(handle));

free(pr_1); free(vertex_dim); free(vertex_dimT);

free(CSC_input);

return 0;

}

4. nvGRAPH SSSP example

void check(nvgraphStatus_t status) {

if (status != NVGRAPH_STATUS_SUCCESS) {

printf("ERROR : %d\n",status);

exit(0);

}

}

int main(int argc, char **argv) {

const size_t  n = 6, nnz = 10, vertex_numsets = 1, edge_numsets = 1;

float *sssp_1_h;

void** vertex_dim;

// nvgraph variables

nvgraphStatus_t status; nvgraphHandle_t handle;

nvgraphGraphDescr_t graph;

nvgraphCSCTopology32I_t CSC_input;

cudaDataType_t edge_dimT = CUDA_R_32F;

cudaDataType_t* vertex_dimT;

// Init host data

sssp_1_h = (float*)malloc(n*sizeof(float));

vertex_dim  = (void**)malloc(vertex_numsets*sizeof(void*));

vertex_dimT = (cudaDataType_t*)malloc(vertex_numsets*sizeof(cudaDataType_t));

CSC_input = (nvgraphCSCTopology32I_t) malloc(sizeof(struct nvgraphCSCTopology32I_st));

vertex_dim[0]= (void*)sssp_1_h; vertex_dimT[0] = CUDA_R_32F;

float weights_h[] = {0.333333, 0.5, 0.333333, 0.5, 0.5, 1.0, 0.333333, 0.5, 0.5, 0.5};

int destination_offsets_h[] = {0, 1, 3, 4, 6, 8, 10};

int source_indices_h[] = {2, 0, 2, 0, 4, 5, 2, 3, 3, 4};

check(nvgraphCreate(&handle));

check(nvgraphCreateGraphDescr (handle, &graph));

CSC_input->nvertices = n; CSC_input->nedges = nnz;

CSC_input->destination_offsets = destination_offsets_h;

CSC_input->source_indices = source_indices_h;

// Set graph connectivity and properties (tranfers)

check(nvgraphSetGraphStructure(handle, graph, (void*)CSC_input, NVGRAPH_CSC_32));

check(nvgraphAllocateVertexData(handle, graph, vertex_numsets, vertex_dimT));

check(nvgraphAllocateEdgeData  (handle, graph, edge_numsets, &edge_dimT));

check(nvgraphSetEdgeData(handle, graph, (void*)weights_h, 0));

// Solve

int source_vert = 0;

check(nvgraphSssp(handle, graph, 0,  &source_vert, 0));

// Get and print result

check(nvgraphGetVertexData(handle, graph, (void*)sssp_1_h, 0));

//Clean

free(sssp_1_h); free(vertex_dim);

free(vertex_dimT); free(CSC_input);

check(nvgraphDestroyGraphDescr(handle, graph));

check(nvgraphDestroy(handle));

return 0;

}

5. nvGRAPH Semi-Ring SPMV example

void check(nvgraphStatus_t status) {

if (status != NVGRAPH_STATUS_SUCCESS) {

printf("ERROR : %d\n",status);

exit(0);

}

}

int main(int argc, char **argv) {

size_t  n = 5, nnz = 10, vertex_numsets = 2, edge_numsets = 1;

float alpha = 1.0, beta = 0.0;

void *alpha_p = (void *)&alpha, *beta_p = (void *)&beta;

void** vertex_dim;

cudaDataType_t edge_dimT = CUDA_R_32F;

cudaDataType_t* vertex_dimT;

// nvgraph variables

nvgraphStatus_t status; nvgraphHandle_t handle;

nvgraphGraphDescr_t graph;

nvgraphCSRTopology32I_t CSR_input;

// Init host data

vertex_dim  = (void**)malloc(vertex_numsets*sizeof(void*));

vertex_dimT = (cudaDataType_t*)malloc(vertex_numsets*sizeof(cudaDataType_t));

CSR_input = (nvgraphCSRTopology32I_t) malloc(sizeof(struct nvgraphCSRTopology32I_st));

float x_h[] = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f};

float y_h[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};

vertex_dim[0]= (void*)x_h; vertex_dim[1]= (void*)y_h;

vertex_dimT[0] = CUDA_R_32F; vertex_dimT[1]= CUDA_R_32F;

float weights_h[] = {1.0f, 4.0f, 2.0f, 3.0f, 5.0f, 7.0f, 8.0f, 9.0f, 6.0f, 1.5f};

int source_offsets_h[] = {0, 2, 4, 7, 9, 10};

int destination_indices_h[] = {0, 1, 1, 2, 0, 3, 4, 2, 4, 2};

check(nvgraphCreate(&handle));

check(nvgraphCreateGraphDescr(handle, &graph));

CSR_input->nvertices = n; CSR_input->nedges = nnz;

CSR_input->source_offsets = source_offsets_h;

CSR_input->destination_indices = destination_indices_h;

// Set graph connectivity and properties (tranfers)

check(nvgraphSetGraphStructure(handle, graph, (void*)CSR_input, NVGRAPH_CSR_32));

check(nvgraphAllocateVertexData(handle, graph, vertex_numsets, vertex_dimT));

for (int i = 0; i < vertex_numsets; ++i)

check(nvgraphSetVertexData(handle, graph, vertex_dim[i], i));

check(nvgraphAllocateEdgeData  (handle, graph, edge_numsets, &edge_dimT));

check(nvgraphSetEdgeData(handle, graph, (void*)weights_h, 0));

// Solve

check(nvgraphSrSpmv(handle, graph, 0, alpha_p, 0, beta_p, 1, NVGRAPH_PLUS_TIMES_SR));

//Get result

check(nvgraphGetVertexData(handle, graph, (void*)y_h, 1));

//Clean

check(nvgraphDestroyGraphDescr(handle, graph));

check(nvgraphDestroy(handle));

free(vertex_dim); free(vertex_dimT); free(CSR_input);

return 0;

}

6. nvGRAPH Triangles Counting example

#include "stdlib.h"

#include "inttypes.h"

#include "stdio.h"

#include "nvgraph.h"

#define check( a ) \

{\

nvgraphStatus_t status = (a);\

if ( (status) != NVGRAPH_STATUS_SUCCESS) {\

printf("ERROR : %d in %s : %d\n", status, __FILE__ , __LINE__ );\

exit(0);\

}\

}

int main(int argc, char **argv)

{

// nvgraph variables

nvgraphHandle_t handle;

nvgraphGraphDescr_t graph;

nvgraphCSRTopology32I_t CSR_input;

// Init host data

CSR_input = (nvgraphCSRTopology32I_t) malloc(sizeof(struct nvgraphCSRTopology32I_st));

// Undirected graph:

// 0       2-------4

//  \     / \     / \

//   \   /   \   /   \

//    \ /     \ /     \

//     1-------3-------5

// 3 triangles

// CSR of lower triangular of adjacency matrix:

const size_t n = 6, nnz = 8;

int source_offsets[] = {0, 0, 1, 2, 4, 6, 8};

int destination_indices[] = {0, 1, 1, 2, 2, 3, 3, 4};

check(nvgraphCreate(&handle));

check(nvgraphCreateGraphDescr (handle, &graph));

CSR_input->nvertices = n;

CSR_input->nedges = nnz;

CSR_input->source_offsets = source_offsets;

CSR_input->destination_indices = destination_indices;

// Set graph connectivity

check(nvgraphSetGraphStructure(handle, graph, (void*)CSR_input, NVGRAPH_CSR_32));

uint64_t trcount = 0;

check(nvgraphTriangleCount(handle, graph, &trcount));

printf("Triangles count: %" PRIu64 "\n", trcount);

free(CSR_input);

check(nvgraphDestroyGraphDescr(handle, graph));

check(nvgraphDestroy(handle));

return 0;

}

7. nvGRAPH Traversal example

void check_status(nvgraphStatus_t status){

if ((int)status != 0)    {

printf("ERROR : %d\n",status);

exit(0);

}

}

int main(int argc, char **argv){

//Example of graph (CSR format)

const size_t  n = 7, nnz = 12, vertex_numsets = 2, edge_numset = 0;

int source_offsets_h[] = {0, 1, 3, 4, 6, 8, 10, 12};

int destination_indices_h[] = {5, 0, 2, 0, 4, 5, 2, 3, 3, 4, 1, 5};

//where to store results (distances from source) and where to store results (predecessors in search tree)

int bfs_distances_h[n], bfs_predecessors_h[n];

// nvgraph variables

nvgraphStatus_t status;

nvgraphHandle_t handle;

nvgraphGraphDescr_t graph;

nvgraphCSRTopology32I_t CSR_input;

cudaDataType_t* vertex_dimT;

size_t distances_index = 0;

size_t predecessors_index = 1;

vertex_dimT = (cudaDataType_t*)malloc(vertex_numsets*sizeof(cudaDataType_t));

vertex_dimT[distances_index] = CUDA_R_32I;

vertex_dimT[predecessors_index] = CUDA_R_32I;

//Creating nvgraph objects

check_status(nvgraphCreate (&handle));

check_status(nvgraphCreateGraphDescr (handle, &graph));

// Set graph connectivity and properties (tranfers)

CSR_input = (nvgraphCSRTopology32I_t) malloc(sizeof(struct nvgraphCSCTopology32I_st));

CSR_input->nvertices = n;

CSR_input->nedges = nnz;

CSR_input->source_offsets = source_offsets_h;

CSR_input->destination_indices = destination_indices_h;

check_status(nvgraphSetGraphStructure(handle, graph, (void*)CSR_input, NVGRAPH_CSR_32));

check_status(nvgraphAllocateVertexData(handle, graph, vertex_numsets, vertex_dimT));

int source_vert = 1;

//Setting the traversal parameters

nvgraphTraversalParameter_t traversal_param;

nvgraphTraversalParameterInit(&traversal_param);

nvgraphTraversalSetDistancesIndex(&traversal_param, distances_index);

nvgraphTraversalSetPredecessorsIndex(&traversal_param, predecessors_index);

nvgraphTraversalSetUndirectedFlag(&traversal_param, false);

//Computing traversal using BFS algorithm

check_status(nvgraphTraversal(handle, graph, NVGRAPH_TRAVERSAL_BFS, &source_vert, traversal_param));

// Get result

check_status(nvgraphGetVertexData(handle, graph, (void*)bfs_distances_h, distances_index));

check_status(nvgraphGetVertexData(handle, graph, (void*)bfs_predecessors_h, predecessors_index));

// expect bfs distances_h = (1 0 1 3 3 2 2147483647)

for (int i = 0; i<n; i++)  printf("Distance to vertex %d: %i\n",i, bfs_distances_h[i]); printf("\n");

// expect bfs predecessors = (1 -1 1 5 5 0 -1)

for (int i = 0; i<n; i++)  printf("Predecessor of vertex %d: %i\n",i, bfs_predecessors_h[i]); printf("\n");

free(vertex_dimT);

free(CSR_input);

check_status(nvgraphDestroyGraphDescr (handle, graph));

check_status(nvgraphDestroy (handle));

return 0;

}

nvGRAPH API参考分析(二)的更多相关文章

  1. nvGRAPH API参考分析(一)

    nvGRAPH API参考分析(一) 本文通过描述nvGRAPH库函数的输入/输出参数,数据类型和错误代码来指定其行为. 1.    返回值nvgraphStatus_t 除以下内容外,所有nvGRA ...

  2. PJSUA2开发文档--第十二章 PJSUA2 API 参考手册

    12 PJSUA2 API 参考手册 12.1 endpoint.hpp PJSUA2基本代理操作.  namespace pj PJSUA2 API在pj命名空间内. 12.1.1 class En ...

  3. Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI

    目录 引言 Search APIs Search API Search Request 可选参数 使用 SearchSourceBuilder 构建查询条件 指定排序 高亮请求 聚合请求 建议请求 R ...

  4. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  5. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  6. SQLite入门与分析(二)---设计与概念(续)

    SQLite入门与分析(二)---设计与概念(续)   写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...

  7. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  8. 透过【百度地图API】分析双闭包问题

    原文:透过[百度地图API]分析双闭包问题 摘要: 有位API爱好者问到,昨天的教程里为什么不使用for循环?他使用for循环后,也发现代码无效.这是什么原因? ------------------- ...

  9. java微信开发API解析(二)-获取消息和回复消息

    java微信开发API解析(二)-获取消息和回复消息 说明 * 本演示样例依据微信开发文档:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/20 ...

随机推荐

  1. 去css 冗余方法

    1.float在某种意义上而言与display:inline-block属性的作用是一模一样的, 所以类似于display:block; float:left; 就是说.float:left 可以让行 ...

  2. ubuntu14.04忽然不能登录,输入密码一直返回登录界面

    解决方法: 1.ctrl + alt + F1进入命令终端 2.重装gdm,sudo apt-get install gdm 3.修改启动顺序:dpkg -reconfigure gdm 4.重启re ...

  3. php、jsp、asp和aspx的区别

    目录 PHP JSP ASP ASP.NET PHP PHP是一种跨平台的服务器端的嵌入式脚本语言.它大量地借用C.Java 和 Perl 语言的语法,并耦合PHP自己的特性,使WEB开发者能够快速地 ...

  4. 神经网络与机器学习 笔记—多层感知器(MLP)

    多层感知器(MLP) Rosenblatt感知器和LMS算法,都是单层的并且是单个神经元构造的神经网络,他们的局限性是只能解决线性可分问题,例如Rosenblatt感知器一直没办法处理简单异或问题.然 ...

  5. GUI简单实战——贪吃蛇

    将前面学到的GUI基础知识完成实战,完成一个简单的贪吃蛇项目 项目功能 用键盘上下左右实现贪吃蛇的自动移动 贪吃蛇吃到食物后,长度加一,分数加一 贪吃蛇吃到自己的身体,则游戏结束 按空格键实现游戏的暂 ...

  6. 缓冲流以及JAVA路径相关问题

    缓冲流 缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO 次数,从而提高读写的效率. 字节缓冲流 按字节处理 字符缓冲流 按字符处理 实例练习:文 ...

  7. C++入门教程之二:变量

    C++入门教程之二:变量 变量,顾名思义,意思是变化的量.变量的定义是计算机语言中能储存计算结果或能表示值的抽象概念.一个基本的程序需要变量,因此变量是程序设计中的一大重点. 变量基本结构 var_t ...

  8. Spring Cloud Alibaba(10)---Sentinel控制台搭建+整合SpringCloudAlibaba

    上一篇博客讲了Sentinel一些概念性的东西 Spring Cloud Alibaba(9)---Sentinel概述 这篇博客主要讲 Sentinel控制台搭建,和 整合SpringCloudAl ...

  9. Linux的三剑客

    首先,需要介绍一下管道和正则表达式,因为它经常和Linux三剑客一起使用. 一.管道Linux 提供管道符"|",将两个命令隔开,管道符左边命令的输出作为管道符右边命令的输入. c ...

  10. UVa OJ 455 Periodic Strings

     Periodic Strings  A character string is said to have period k if it can be formed by concatenating ...