Skip to content

Instantly share code, notes, and snippets.

@corburn
Last active February 8, 2017 22:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save corburn/79ccc4cf64f4b0a734dd2bb63dc1809f to your computer and use it in GitHub Desktop.
Save corburn/79ccc4cf64f4b0a734dd2bb63dc1809f to your computer and use it in GitHub Desktop.

conda install -c https://conda.binstar.org/rsignell geojson

A typical GPU program

  • CPU allocates storage on the GPU cudaMalloc
  • CPU copied input data from CPU to GPU cudaMemcpy
  • CPU launches kernels on GPU to process the data kernel launch
  • CPU copies result back from GPU to CPU cudaMemcpy
// __global__ is a declaration specifier. It indicates the function is a CUDA kernel.
__global__ void square(float *d_out, float *d_in) {
  int idx threadIdx.x;
  float f = d_in[idx];
  d_out[idx] = f * f;
}

int main(int argc, char **argv) {
  const int ARRAY_SIZE = 64;
  const int ARRAY_BYTES = ARRAY_SIZE*sizeof(float);

  cudaMalloc((void **) &d_out, ARRAY_BYTES);
  // Transfer the input array to the GPU
  cudaMemcpy(d_in, h_in, ARRAY_BYTES, cudaMemcpyHostToDevice);
  // Launch the kernel, named square, on one block of 64 elements and the arguments to the kernel are two pointers: d_out and d_in
  // The kernel can only be called on GPU data, _not_ CPU data.
  square<<<1, ARRAY_BYTES>>>(d_out, d_in);
  // Transfer the result array to the CPU
  cudaMemcpy(h_out, d_out, ARRAY_BYTES, cudaMemcpyDeviceToHost);
  // Free GPU allocation
  cudaFree(d_in);
  cudaFree(d_out);
  return 0;
}

Configuring the kernel launch

// Kernel <<< Grid of Blocks, Block of Threads >>>
// shmem is shared memory per block in bytes. Defaults to 0 if unused.
square<<<dim3(bx,by,bz), dim3(tx,ty,tz), shmem>>>
  • threadIdx: thread within block (threadIdx.x, threadIdx.y, threadIdx.z)
  • blockDim: size of a block
  • blockIdx: block within grid
  • gridDim: size of grid

Parallel Communication Patterns

  • Map

    • one-to-one
  • Gather

    • many-to-one
  • Scatter

    • one-to-many
  • Stencil:

    • several-to-one (similar to gather, but more restricted)
    • Tasks read input from a fixed neighborhood in an array (eg. 2D/3D Von Neumann or 2D Moore)
  • Transpose: Tasks reoder elements in memory (eg. Array of Structures <==> Structure of Arrays)

    • one-to-one
  • Reduce

    • all-to-one
  • Scan/sort

    • all-to-all
    • all of the input can affect the destination of the output
  • Thread block: a group of threads that cooperate to solve a sub-problem

// Remove GOPATH prefix from the stacktrace
// https://github.com/golang/go/issues/13809#issuecomment-168874760
go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH

https://blog.filippo.io/shrink-your-go-binaries-with-this-one-weird-trick/ https://golang.org/cmd/link/ Remove debugging symbols with -ldflags="-s -w" to reduce binary size.

Profile

import (
	"flag"
	"github.com/pkg/profile"
)

var (
	profileFlag string
)

func init() {
	flag.StringVar(&profileFlag, "profile", "", "(dev) enable profiling one of `cpu|mem|block`")
}

switch strings.ToLower(profileFlag) {
case "":
case "cpu":
	defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
case "mem":
	defer profile.Start(profile.MemProfile, profile.ProfilePath(".")).Stop()
case "block":
	defer profile.Start(profile.BlockProfile, profile.ProfilePath(".")).Stop()
default:
	log.Printf("invalid profile: %s\n", profileFlag)
	flag.Usage()
	os.Exit(1)
}

Read from Stdin

fi, err := f.Stat()
if err == nil && fi.Mode()&os.ModeCharDevice == 0 {
	// Note that a non-nil error is not a problem. Windows
	// will not create a stdin if there is no pipe, which
	// produces an error when calling Stat(). But Unix will
	// make one either way, which is why we also check that
	// bitmask.
	// BUG: Reading from stdin after this fails (e.g. for the let's encrypt email address) (OS X)
	confBody, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}
	return CaddyfileInput{
		Contents: confBody,
		Filepath: f.Name(),
	}, nil
}
const MaxUint = ^uint(0) 
const MinUint = 0 
const MaxInt = int(MaxUint >> 1) 
const MinInt = -MaxInt - 1

Error Handling

http://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully

  • Sentinel Errors
  • Error Types
  • Opaque Errors
errors.New("error message")
fmt.Errorf("error message")

Sentinel Errors

package io
import "errors"
var EOF = errors.New("EOF")

Error Types

type MyError struct {
        Cause error
        Msg string
        File string
        Line int
}

func (e *MyError) Error() string { 
        return fmt.Sprintf("%s:%d: %s”, e.File, e.Line, e.Msg)
}

return &MyError{"Something happened", “server.go", 42}
err := something()
switch err := err.(type) {
case nil:
        // call succeeded, nothing to do
case *MyError:
        fmt.Println(“error occurred on line:”, err.Line)
default:
// unknown error
}

Version

package main

import (
	"flag"
)

// Build information obtained with the help of -ldflags
var (
	appVersion = "(untracked dev build)" // inferred at startup
	devBuild   = true                    // inferred at startup

	buildDate        string // date -u
	gitTag           string // git describe --exact-match HEAD 2> /dev/null
	gitNearestTag    string // git describe --abbrev=0 --tags HEAD
	gitCommit        string // git rev-parse HEAD
	gitShortStat     string // git diff-index --shortstat
	gitFilesModified string // git diff-index --name-only HEAD
)

func init() {
	caddy.TrapSignals()
	setVersion()
	flag.BoolVar(&https.Agreed, "agree", false, "Agree to Let's Encrypt Subscriber Agreement")
	flag.StringVar(&https.CAUrl, "ca", "https://acme-v01.api.letsencrypt.org/directory", "Certificate authority ACME server")
	flag.StringVar(&conf, "conf", "", "Configuration file to use (default="+caddy.DefaultConfigFile+")")
	flag.StringVar(&cpu, "cpu", "100%", "CPU cap")
	flag.StringVar(&https.DefaultEmail, "email", "", "Default Let's Encrypt account email address")
	flag.DurationVar(&caddy.GracefulTimeout, "grace", 5*time.Second, "Maximum duration of graceful shutdown")
	flag.StringVar(&caddy.Host, "host", caddy.DefaultHost, "Default host")
	flag.BoolVar(&caddy.HTTP2, "http2", true, "Use HTTP/2")
	flag.StringVar(&logfile, "log", "", "Process log file")
	flag.StringVar(&caddy.PidFile, "pidfile", "", "Path to write pid file")
	flag.StringVar(&caddy.Port, "port", caddy.DefaultPort, "Default port")
	flag.BoolVar(&caddy.Quiet, "quiet", false, "Quiet mode (no initialization output)")
	flag.StringVar(&revoke, "revoke", "", "Hostname for which to revoke the certificate")
	flag.StringVar(&caddy.Root, "root", caddy.DefaultRoot, "Root path to default site")
	flag.BoolVar(&version, "version", false, "Show version")
	flag.BoolVar(&directives, "directives", false, "List supported directives")
}

func main() {
	flag.Parse()
	
	// set up process log before anything bad happens
	switch logfile {
	case "stdout":
		log.SetOutput(os.Stdout)
	case "stderr":
		log.SetOutput(os.Stderr)
	case "":
		log.SetOutput(ioutil.Discard)
	default:
		log.SetOutput(&lumberjack.Logger{
			Filename:   logfile,
			MaxSize:    100,
			MaxAge:     14,
			MaxBackups: 10,
		})
	}
	
	if version {
		fmt.Printf("%s %s\n", appName, appVersion)
		if devBuild && gitShortStat != "" {
			fmt.Printf("%s\n%s\n", gitShortStat, gitFilesModified)
		}
		os.Exit(0)
	}
}

go build -ldflags "-X main.Version=1.0" myapp.go

Go Doc Highlights

https://golang.org/cmd/go/

Go generate sets several variables when it runs the generator:

$GOARCH
	The execution architecture (arm, amd64, etc.)
$GOOS
	The execution operating system (linux, windows, etc.)
$GOFILE
	The base name of the file.
$GOLINE
	The line number of the directive in the source file.
$GOPACKAGE
	The name of the package of the file containing the directive.
$DOLLAR
	A dollar sign.

If Guards

ifndef GIRINST_USERNAME
$(error GIRINST_USERNAME is not set. A valid girinst.org account is required to download the repeatmaskerlibraries)
endif

ifndef GIRINST_PASSWORD
$(error GIRINST_PASSWORD is not set. A valid girinst.org account is required to download the repeatmaskerlibraries)
endif

Expect interactive

#exp_internal 1; 
# http://www.repeatmasker.org/RMDownload.html
${LOCAL}/RepeatMasker/4.0.6: ${SRC}/RepeatMasker/repeatmaskerlibraries-20150807 ${LOCAL}/TRF/4.0.4 ${LOCAL}/perl/5.22.0
        export PATH="${LOCAL}/TRF/4.0.4/trf:${PATH}"; \
        mkdir -p $@ && cp -r $</* $@/ && \
        cd $@; set -x; \
        expect -c 'spawn perl ./configure; \
        expect "<PRESS ENTER TO CONTINUE>\r"; \
        send "\r"; \
        expect "Enter path \\\[ /usr/bin/perl \\\]: "; \
        send "env\r"; \
        expect "Enter path \\\[ * \\\]: "; \
        send "$@\r"; \
        expect "Enter path \\\[ * \\\]: "; \
        send "${LOCAL}/TRF/4.0.4/trf\r"; \
        interact; \
        expect eof'
/**
 * bar demonstrates a function with a jsdoc comment.
 * @param  {String} bar A parameter to modify the foo action
 * @return {Object} Empty object.
 */
function foo(bar) {
  return {};
}
/*
Graceful shutdown
https://www.npmjs.com/package/nodemon
*/
process.once('SIGUSR2', function () {
  gracefulShutdown(function () {
    process.kill(process.pid, 'SIGUSR2');
  });
});

Unofficial shell strict mode: set -euo pipefail

Ensure the interpreter used is the first one on your environment $PATH

#!/usr/bin/env python

#!/usr/bin/env perl

Write to STDERR: >&2 echo "error"

Run a command on a collection of files: find ${ROOT_DIRECTORY} -name "${FILENAME_PATTERN}" -type f -print0 | xargs -0 -P${NUM_PROCESSES} -I{} sh -c "command {}"

Posix.1-2008

// The sha256sum line should output a line such as: ubuntu-9.10-dvd-i386.iso: OK
sha256sum -c SHA256SUMS 2>&1 | grep OK
```
// Fix PPA GPG keys
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys KEY [KEY...]
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment