Есть ли более эффективный способ конвертировать double в float? - PullRequest
6 голосов
/ 06 октября 2011

Мне нужно преобразовать многомерный двойной массив в массив с неровными числами. Размеры будут варьироваться от [2] [5] до примерно [6] [1024].

Мне было любопытно, как будут работать только зацикливание и приведение двойного к числу с плавающей точкой, и это неплохо, около 225 мкс для массива [2] [5] - вот код:

const int count = 5;
const int numCh = 2;
double[,] dbl = new double[numCh, count];
float[][] flt = new float[numCh][];

for (int i = 0; i < numCh; i++)
{
    flt[i] = new float[count];
    for (int j = 0; j < count; j++)
    {
        flt[i][j] = (float)dbl[i, j];
    }
}

Однако, если есть более эффективные методы, я бы хотел их использовать. Я должен отметить, что я рассчитал ТОЛЬКО два вложенных цикла, а не распределения перед ним.

После нескольких дополнительных экспериментов я думаю, что 99% времени сгорает на петлях, даже без назначения!

Ответы [ 4 ]

6 голосов
/ 06 октября 2011

Это будет работать быстрее, для небольших данных не стоит делать Parallel.For(0, count, (j) => На самом деле, оно работает намного медленнее для очень маленьких данных, поэтому я закомментировал этот раздел.

double* dp0;
float* fp0;

fixed (double* dp1 = dbl)
{
    dp0 = dp1;

    float[] newFlt = new float[count];
    fixed (float* fp1 = newFlt)
    {
        fp0 = fp1;
        for (int i = 0; i < numCh; i++)
        {
            //Parallel.For(0, count, (j) =>
            for (int j = 0; j < count; j++)
            {
                fp0[j] = (float)dp0[i * count + j];
            }
            //});
            flt[i] = newFlt.Clone() as float[];
        }
     }
  }

Это работаетбыстрее, потому что двойной доступ к двойным массивам [,] действительно обременителен в .NET из-за проверки границ массива.newFlt.Clone() просто означает, что мы не исправляем и не фиксируем новые указатели все время (поскольку при этом возникают небольшие накладные расходы)

Вам нужно будет запустить его с тегом кода unsafe и скомпилироватьс /UNSAFE

Но на самом деле вы должны работать с данными ближе к 5000 x 5000, а не к 5 x 2, если что-то занимает менее 1000 мс, вам нужно либо добавить больше циклов, либо увеличить данные, потому что при этомНебольшой всплеск активности процессора может добавить много шума вашему профилированию.

0 голосов
/ 06 октября 2011

Если бы вы могли также использовать списки в вашем случае, вы можете использовать подход LINQ:

List<List<double>> t = new List<List<double>>();
//adding test data
t.Add(new List<double>() { 12343, 345, 3, 23, 2, 1 });
t.Add(new List<double>() { 43, 123, 3, 54, 233, 1 });
//creating target
List<List<float>> q;
//conversion
q = t.ConvertAll<List<float>>(
        (List<double> inList) => 
        {
            return inList.ConvertAll<float>((double inValue) => { return (float)inValue; });
        }
     );

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

0 голосов
/ 06 октября 2011

Я действительно не думаю, что вы можете оптимизировать свой код намного больше, один вариант - сделать ваш код параллельным, но для вашего размера входных данных ([2] [5] до [6] [1024]) Я не думаю, что вы бы так много заработали, если бы у вас была хоть какая-то прибыль. На самом деле, я бы даже не стал оптимизировать этот кусок кода ...

В любом случае, чтобы оптимизировать это, единственное, что я бы сделал (если это соответствует тому, что вы хотите сделать), это просто использовал бы массивы фиксированной ширины вместо зубчатых, даже если бы вы тратили на это память. .

0 голосов
/ 06 октября 2011

В вашем примере - я думаю, вы не столько измеряете сравнение double / float (которое должно быть внутренней инструкцией процессора), сколько обращается к массиву (который имеет много переадресаций плюс очевидные проверки .... aray delimiter (для индекс массива исключений границ).

Я бы предложил синхронизировать тест без массивов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...