2009-06-10 5 views
5

¿Esto tiene algún equivalente en c?Rendimiento en C#

+2

¡Ni siquiera cerca! –

+0

¿Por qué necesita rendimiento? Si tiene una matriz, puede iterar a través de ella. El rendimiento es relevante para IEnumerables, que generalmente usarías en una situación 'foreach'. Como no puedes 'foreach', ¿por qué necesitarías crear un 'rendimiento'? – DevinB

Respuesta

2

No. Sin embargo, en Windows, puede usar fibras para lograr un efecto similar.

7

Mientras que C no tiene el mismo concepto que el rendimiento en lo que respecta a enumerar más de una colección que tiene la capacidad de crear corrutinas y fibras.

Éstos son algunos artículos de Wikipedia, que pueden ser de interés:

http://en.wikipedia.org/wiki/Setcontext http://en.wikipedia.org/wiki/Setjmp/longjmp

+0

Creo que esto es demasiado complicado. La mejor metodología sería simplemente crear una estructura que tuviera una variable de índice de rendimiento y su matriz en ella, luego incrementar el índice cada vez que 'cedería'. De esta forma, su 'rendimiento' simplemente saca el valor de la matriz del punto de índice de rendimiento. – DevinB

+1

No digo que no sea complicado, solo que ese es el equivalente en C. Hay muchas formas de resolver este problema ... por eso escribimos software =) – jonnii

1

No. Sin embargo, se puede lograr similares efectos en C con el uso de setjmp, longjmp, pero es muy difícil.

11

El compilador implementa el rendimiento como una clase personalizada que implementa una máquina de estados. Si bien no puede obtener la sintaxis con la misma facilidad (a menos que use el método de fibra previamente especificado), puede replicar los resultados usted mismo de manera bastante simple, aunque es bastante tedioso. Así es como (voy a mostrar en C#, que tendrá que hacer lo que es apropiado en C++ dependiendo de los tipos que está utilizando):

Suponiendo que el siguiente código:

public IEnumerable<T> GetOddStrings(
    IEnumerable<IEnumerable<string>> stringCollections) 
{ 
    foreach(var stringCollection in stringCollections) 
     foreach(var str in stringCollection) 
     { 
     if(str.Length %2 != 0) yield return str; 
     if(str.Length == 42) yield break; // 42 is BAD! Stop immediately 
     } 
} 

1) Desenrollar todo foreach métodos en empadronador explícita llama:

public IEnumerable<T> GetOddStrings(
    IEnumerable<IEnumerable<string>> stringCollections) 
{ 
    var firstEnumerator = stringCollection.GetEnumerator(); 
    while(firstEnumerator.MoveNext()) 
    { 
    var secondEnumerator = firstEnumerator.Current.GetEnumerator(); 
    while(secondEnumerator.MoveNext()) 
    { 
     var str= secondEnumerator.Current; 
     if(str.Length %2 != 0) yield return str; 
     if(str.Length == 42) yield break; 
    } 
    } 
} 

2) mover todas las variables locales a la parte superior del método:

public IEnumerable<T> GetOddStrings(
    IEnumerable<IEnumerable<string>> stringCollections) 
{ 
    IEnumerator<IEnumerable<string>> firstEnumerator; 
    IEnumerator<string> secondEnumerator; 
    string str; 

    firstEnumerator = stringCollections.GetEnumerator(); 
    while(firstEnumerator.MoveNext()) 
    { 
    secondEnumerator = firstEnumerator.Current.GetEnumerator(); 
    while(secondEnumerator.MoveNext()) 
    { 
     str= secondEnumerator.Current; 
     if(str.Length %2 != 0) yield return str; 
     if(str.Length == 42) yield break; 
    } 
    } 
} 

3) Mover a una construcción de bucle con una instrucción de conmutación anidada.
a) Cambia el estado y continúa el ciclo para cada retorno de rendimiento. b) Invierta si las condiciones son c) Rendimiento de rotura para cada condición de salida (a continuación, invertimos el if).

public IEnumerable<T> GetOddStrings(
    IEnumerable<IEnumerable<string>> stringCollections) 
{ 
    IEnumerator<IEnumerable<string>> firstEnumerator; 
    IEnumerator<string> secondEnumerator; 
    string str; 
    int state = 0; 

    while(true) 
    { 
    switch(state) 
    { 
     case 0: 
     firstEnumerator = stringCollections.GetEnumerator(); 
     // This could be "yield break" but I want to show how you 
     // could split ifs with significant code in the else 
     if(!firstEnumerator.MoveNext()) 
     { 
      state = 1; 
      continue; 
     } 

     secondEnumerator = firstEnumerator.Current; 
     if(!secondEnumerator.MoveNext) continue; 
     state = 2; 
     if(str.Length %2 != 0) yield return str; 
     continue; 

     case 1: 
     yield break; 

     case 2: 
     if(str.Length == 42) yield break; 
     state = 0; 
     continue; 
    } 
    } 
} 

4) Mover a una clase y devolver la clase de su método: a) descansos de rendimiento se convierten en "return false;" b) los rendimientos vuelven a ser "this.Current = ??; return true;"

public IEnumerable<T> GetOddStrings(
    IEnumerable<IEnumerable<string>> stringCollections) 
{ 
    return new OddStringEnumerable(stringCollections); 
} 

private class OddStringEnumerable : IEnumerable<string> 
{ 
    IEnumerable<IEnumerable<string>> stringCollections; 
    IEnumerator<IEnumerable<string>> firstEnumerator; 
    IEnumerator<string> secondEnumerator; 
    string str; 
    int state; 

    public OddStringEnumerable(IEnumerable<IEnumerable<string>> stringCollections) 
    { 
    this.stringCollections = stringCollections; 
    } 

    public string Current { get; private set; } 

    public bool MoveNext() 
    { 
    while(true) 
    { 
     switch(state) 
     { 
     case 0: 
      firstEnumerator = this.stringCollections.GetEnumerator(); 
      if(!this.firstEnumerator.MoveNext()) 
      { 
      this.state = 1; 
      continue; 
      } 

      this.secondEnumerator = this.firstEnumerator.Current; 
      if(!secondEnumerator.MoveNext) continue; 

      this.state = 2; 
      if(str.Length %2 != 0) 
      { 
      this.Current = str; 
      return true; 
      } 
      continue; 

     case 1: 
      return false; 

     case 2: 
      if(str.Length == 42) return false; 
      this.state = 0; 
      continue; 
     } 
    } 
    } 
} 

5) Optimizar según corresponda.

5

Coroutines in C utiliza algunos hacks de preprocesador, pero implementa un bastante natural (en relación con cualquier otra cosa en C) yield.

Mientras que iba a escribir esto en Python:

"""This is actually a built-in function. 
def range(start, stop, step): 
    i = start 
    while i < stop: 
     yield i 
     i = i + step 
""" 

if __name__ == '__main__': 
    import sys 
    start = int(sys.argv[1]) if len(sys.argv) > 2 else 0 
    stop = int(sys.argv[2]) if len(sys.argv) > 2 else int(sys.argv[1]) 
    step = int(sys.argv[3]) if len(sys.argv) > 3 else 1 
    for i in range(start, stop, step): 
     print i, 
    print 

coroutine.h le permite escribir esto en C:

#include <coroutine.h> 
#include <stdio.h> 

int range(int start, int stop, int step) { 
    static int i; 

    scrBegin; 
    for (i = start; i < stop; i += step) 
     scrReturn(i); 
    scrFinish(start - 1); 
} 

int main(int argc, char **argv) { 
    int start, stop, step, i; 

    start = argc > 2 ? atoi(argv[1]) : 0; 
    stop = argc > 2 ? atoi(argv[2]) : atoi(argv[1]); 
    step = argc > 3 ? atoi(argv[3]) : 1; 

    while ((i = range(start, stop, step)) >= start) 
     printf("%d ", i); 
    printf("\n"); 
} 
 
$ cc range.c 
$ ./a.out 10 
0 1 2 3 4 5 6 7 8 9 

Para algo más complejo y que requiere reentrada, la Hamming numbers en Python :

def hamming(): 
    yield 1 

    i2 = (2*x for x in hamming()) 
    i3 = (3*x for x in hamming()) 
    i5 = (5*x for x in hamming()) 

    m2, m3, m5 = i2.next(), i3.next(), i5.next() 

    while True: 
     if m2 < m3: 
      if m2 < m5: 
       yield m2 
       m2 = i2.next() 
      else: 
       if m2 > m5: yield m5 
       m5 = i5.next() 
     elif m2 == m3: m3 = i3.next() 
     elif m3 < m5: 
      yield m3 
      m3 = i3.next() 
     else: 
      if m3 > m5: yield m5 
      m5 = i5.next() 

if __name__ == '__main__': 
    import sys 
    it = hamming() 
    for i in range(str(sys.argv[1]) if len(sys.argv) > 1 else 25): 
     print it.next(), 
    print 

y C:

#include <coroutine.h> 
#include <stdio.h> 

int hamming(ccrContParam) { 
    ccrBeginContext; 
    ccrContext z[3]; 
    int m2, m3, m5; 
    ccrEndContext(state); 

    ccrBegin(state); 
    state->z[0] = state->z[1] = state->z[2] = 0; 
    ccrReturn(1); 

#define m2_next (2*hamming(&state->z[0])) 
#define m3_next (3*hamming(&state->z[1])) 
#define m5_next (5*hamming(&state->z[2])) 

    state->m2 = m2_next, state->m3 = m3_next, state->m5 = m5_next; 

    while (1) { 
     if (state->m2 < state->m3) { 
      if (state->m2 < state->m5) { 
       ccrReturn(state->m2); 
       state->m2 = m2_next; 
      } else { 
       if (state->m2 > state->m5) ccrReturn(state->m5); 
       state->m5 = m5_next; 
      } 
     } else if (state->m2 == state->m3) state->m3 = m3_next; 
     else if (state->m3 < state->m5) { 
      ccrReturn(state->m3); 
      state->m3 = m3_next; 
     } else { 
      if (state->m3 > state->m5) ccrReturn(state->m5); 
      state->m5 = m5_next; 
     } 
    } 
    ccrFinish(-1); 
} 

int main(int argc, char **argv) { 
    int count = argc > 1 ? atoi(argv[1]) : 25, i; 
    ccrContext z = 0; 

    for (i = 0; i < count; i++) 
     printf("%d ", hamming(&z)); 
    printf("\n"); 
} 
 
$ cc hamming.c 
$ ./a.out 
1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36 40 45 48 50 54 
1

en C# rendimientos simplifica la creación de IEnumberables para una colección.

En C++ debe usar los Iterators de STL.