Skip to content

Instantly share code, notes, and snippets.

@samuell
Created June 21, 2013 09:17
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save samuell/5829991 to your computer and use it in GitHub Desktop.
/// --------------------------------------------------------------------
// Dummy processing DNA code (by taking base complement)
// Threaded version
// Author: Samuel Lampa, samuel.lampa@gmail.com
// Date: 2013-06-21
// --------------------------------------------------------------------
package main
import (
"fmt"
"bufio"
"os"
"log"
"runtime"
)
const(
BUFSIZE = 512
)
func main() {
// Set the number of Operating System-threads to use
numThreads := 2 // runtime.NumCPU() - 1
fmt.Println("Starting ", numThreads, " threads ...")
runtime.GOMAXPROCS(numThreads)
// Read DNA file
inFileName := "Homo_sapiens.GRCh37.67.dna_rm.chromosome.Y.fa"
fileReadChan := fileReaderGen(inFileName)
// Setting up a sequence of dummy processing, where
// each operation is done in a separate goroutine
// and thus possibly will be multiplexed upon an OS
// thread), and communication is done through channels
// between each pair of goroutines.
complChan1 := baseComplementGen(fileReadChan)
complChan2 := baseComplementGen(complChan1)
complChan3 := baseComplementGen(complChan2)
complChan4 := baseComplementGen(complChan3)
// Read the last channel in the "pipeline"
for line := range complChan4 {
if len(line) > 0 {
fmt.Println(string(line))
}
}
}
// create a goroutine that will read the dna file
// line by line. it returns a channel which can be
// read line by line, to "draw" the goroutine's execution.
func fileReaderGen(filename string) chan []byte {
fileReadChan := make(chan []byte, BUFSIZE)
go func() {
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
} else {
scan := bufio.NewScanner(file)
for scan.Scan() {
fileReadChan <- scan.Bytes()
}
close(fileReadChan)
fmt.Println("Closed file reader channel")
}
}()
return fileReadChan
}
// Initiates a goroutine that will take the base complement
// of each line in the input channel specified, and returns
// an output channel that can be read line by line.
func baseComplementGen(inChan chan []byte) chan []byte {
returnChan := make(chan []byte, BUFSIZE)
go func() {
for line := range inChan {
for pos := range line {
if line[pos] == 'A' {
line[pos] = 'T'
} else if line[pos] == 'T' {
line[pos] = 'A'
} else if line[pos] == 'C' {
line[pos] = 'G'
} else if line[pos] == 'G' {
line[pos] = 'C'
}
}
returnChan <- append([]byte(nil), line...)
}
close(returnChan)
fmt.Println("Closed base complement generator channel")
}()
return returnChan
}
@samuell
Copy link
Author

samuell commented Jun 21, 2013

[samuel gotest]$ go build -o basecompl_par basecompl_par.go 
[samuel gotest]$ for i in $(seq 1 1 3); do echo "---"; time ./basecompl_par > out.tmp; done;

---

real    0m4.125s
user    0m6.068s
sys 0m2.092s

---

real    0m4.418s
user    0m6.168s
sys 0m2.128s

---

real    0m4.160s
user    0m6.104s
sys 0m2.116s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment