m-labs / artiq

A leading-edge control system for quantum information experiments
https://m-labs.hk/artiq
GNU Lesser General Public License v3.0
426 stars 198 forks source link

compiler optimization #47

Closed ghost closed 9 years ago

ghost commented 9 years ago
from artiq import *

class PulseNotReceived(Exception):
    pass

class LED(Experiment, AutoDB):
    class DBKeys:
        core = Device()
        ttl0 = Device()
        pmt1 = Device() 

    @kernel
    def run1(self):
        # usual Artiq syntax
        # This takes 55 us to generate ttl0 rising edge 
        self.pmt1.gate_rising(3*ms)
        t0 = self.pmt1.timestamp()
        #if t0 < 0*s:
        #   raise PulseNotReceived
        at(t0)
        delay(55*us)
        self.ttl0.pulse(10*ms)
    @kernel
    def run2(self):
        # bypass compiler and optimize away all rational math 
        # This takes 2.1 us to generate ttl0 rising edge 
        self.pmt1.gate_rising(3*ms)
        syscall('ttl_set_o', syscall('ttl_get', 1, now) + time_to_cycles(2100*ns), 2, True)

    def run(self):
        self.run1()
        #self.run2()
ghost commented 9 years ago

Peter, have you had a chance to look at this?

Context: trigger Core Device based on external stimulus from another laboratory instrument. e.g. Apply 1 KHz square wave to PMT1, ideally QRTIQ generates TTL0 pulse in response after well-defined (short) delay § What is latency? □ 55 us with observation that at(t0); delay(55_us) is faster than at(t0+55_us) □ 1.900 us with a trick to bypass the compiler to remove all rational math ® use syscall() in python Can this optimization be built-in to compiler?

whitequark commented 9 years ago

@jboulder Yes, this should be optimized when the new-py2llvm branch lands.

sbourdeauducq commented 9 years ago

With the new APIs:


from artiq import *

class PulseNotReceived(Exception):
    pass

class Test(EnvExperiment):
    def build(self):
        self.attr_device("core")
        self.attr_device("ttl0")
        self.attr_device("pmt1")

    @kernel
    def run(self):
        self.pmt1.gate_rising(3*ms)
        t0 = self.pmt1.timestamp_mu()
        if t0 < 0:
           raise PulseNotReceived
        at_mu(t0)
        delay(3*us)
        self.ttl0.pulse(10*ms)

The performance should already be much better since there is no rational math anymore.

ghost commented 9 years ago

Yes. This works. Nice! My KC705 requires a delay of 5 us (instead of 3 us).