2014-02-06 3 views
2

Мне никогда не приходилось использовать указатели на C# раньше, однако используемая библиотека требует, чтобы параметры метода передавались как указатели. Библиотека позволяет использовать наборы инструкций SIMD.Попытка заставить указатели работать

Чтобы проверить, как использовать библиотеку, я попытался написать метод, который использует SIMD для вычисления значения косинуса всех элементов массива за один раз.

Это то, что я получил:

double[] ValuesToCalculate = new double[MAX_SIZE]; 
double[] CalculatedCosines = new double[MAX_SIZE]; 

long Result; 
Result = CalculateCosineArray(ValuesToCalculate, CalculatedCosines); 

public static long CalculateCosineArraySIMD(double[] array, double[] result) 
{ 
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start(); 
    for (int i = 0; i < array.Length; i++) 
    { 
     Yeppp.Math.Cos_V64f_V64f(*array, result, MAX_SIZE); 
    } 

    stopwatch.Stop(); 
    return stopwatch.ElapsedMilliseconds; 
} 

Однако я получаю эти ошибки:

The best overloaded method match for 'Yeppp.Math.Cos_V64f_V64f(double*, double*, int)' has some invalid arguments 
Argument 1: cannot convert from 'double[]' to 'double*' 
The * or -> operator must be applied to a pointer 
Argument 2: cannot convert from 'double[]' to 'double*' 

Как получить указатели на работу в этом коде? Опять же, это первый раз, когда указатели появились, когда я использовал C#.

+1

кажется, что ваш метод принимает двойной указатель как второй параметр, но вы передаете двойной массив. –

ответ

4

Методы в Yeppp! библиотека имеет две перегрузки: одну, которая принимает смещение массива +, а другая - указатели (например, если вы хотите называть их stackalloc 'ed memory). Например. для вычисления косинусов Yeppp! предлагает два перегруженных:

Таким образом, ваш пример должен быть переписан как:

double[] ValuesToCalculate = new double[MAX_SIZE]; 
double[] CalculatedCosines = new double[MAX_SIZE]; 

long Result; 
Result = CalculateCosineArray(ValuesToCalculate, CalculatedCosines); 

public static long CalculateCosineArraySIMD(double[] array, double[] result) 
{ 
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start(); 

    Yeppp.Math.Cos_V64f_V64f(array, 0, result, 0, MAX_SIZE); 

    stopwatch.Stop(); 
    return stopwatch.ElapsedMilliseconds; 
} 

Обратите внимание, что только требуется один вызов на массив (даже если вы использовали указатели).

+0

Отлично работает! Спасибо – user9993

+0

Я должен добавить, что ответ @MarcinJuraszek совершенно правильный, и это то, как версия массива внутренне реализована –

5

Вы должны использовать оператор fixed, чтобы получить указатель от массива.

Вероятно, что-то вроде этого:

public static long CalculateCosineArraySIMD(double[] array, double[] result) 
{ 
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start(); 

    fixed (double* arrayPtr = array, resultPtr = result) 
    { 
     Yeppp.Math.Cos_V64f_V64f(arrayPtr, resultPtr, MAX_SIZE); 
    }; 

    stopwatch.Stop(); 
    return stopwatch.ElapsedMilliseconds; 
} 
+0

Bah .. слишком быстро для меня: P –

Смежные вопросы