Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
mat_for_c
164 / 159 / 34
Регистрация: 26.04.2013
Сообщений: 724
Завершенные тесты: 3
#1

Обнулить элементы вектора через __asm - C++

06.04.2014, 15:06. Просмотров 918. Ответов 24
Метки нет (Все метки)

Хочу обнулить элементы вектора через __asm

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <vector>
#include <iostream>
 
using namespace std;
 
void main() {
   vector<vector<int>> v(2, vector <int> (3, 1));
 
   __asm {
      mov ecx, 2
      mov edi, v
      mov eax, dword ptr [edi + 16]
      mov edi, [edi][1]
        
      //mov dword ptr [edi + 8], 0
   cycl:
      mov dword ptr [edi + ecx*4], 0
      //add eax, 4
      loop cycl
   }
     
   for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 3; ++j)
         cout << v[i][j] << " ";
      cout << endl;
   }
}
Сам вопрос: eax и edi имеют разные значения, причем в eax лежит правильный результат. Я же хочу получить доступ ко 2-й строке через индексацию [1]. Как это реализовать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.04.2014, 15:06
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Обнулить элементы вектора через __asm (C++):

Дан список, элементы которого являются координатами вектора. Найти длину вектора - C++
1. Дан список, элементы которого являются координатами вектора в n-мерном пространстве. Найти длину вектора.

STL. Функция, которая будет искать элементы большее среднего арифметического вектора и удалять их из вектора - C++
у меня есть вектор, помогите пожалуйста дописать функцию, которая будет искать элементы большее среднего арифметического вектора и удалять...

Используя алгоритм adjacent_find, обнулить первую пару соседних элементов вектора, имеющих одинаковую чётность - C++
Дан вектор V. Обнулить первую пару соседних элементов, имеющих одинаковую четность. Например, список 1, 2, 3, 4, 6, 8, 3, 1 должен быть...

Заменить первые два нулевые элементы заданного вектора В на два первых НЕ нулевые элементы этого вектора - C++
Дано вектор В, состоящий из N действительных чисел. Заменить первые два нулевые элементы заданного вектора В на два первых НЕ нулевые...

Заменить первых 2 нулевые элементы заданного вектора соответственно на первых 2 не нулевые элементы этого вектора - C++
Заданный вектор Т, который состоит из n действительных чисел. Заменить первых 2 нулевые элементы заданного вектора соответственно на первых...

Обнулить элементы матрицы - C++
Элементы матрицыT стоящие на пересечение четных строк и четных столбцов обнулить! РЕшите плиззззз :(((((((((:gcray2

24
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
06.04.2014, 17:14 #2
mat_for_c, зачем это нужно?
Индексация в векторе - это вызов метода (operator[]). Для того чтобы правильно обратиться к внутренностям вектора через asm нужно знать устройство вектора. А так же про всякие штуки типа выравнивания. Внутреннее устройство вектора в общем случае не обязано быть идентичным на разных компиляторах или версиях одного и того же. Более того, код, который компилятор сделает из С++ кода вектора тоже зависит от многих вещей. Может так случиться, что с одним уровнем оптимизации твой асм будет работать, а с другим - нет.
0
mat_for_c
164 / 159 / 34
Регистрация: 26.04.2013
Сообщений: 724
Завершенные тесты: 3
07.04.2014, 19:19  [ТС] #3
Цитата Сообщение от DrOffset Посмотреть сообщение
Может так случиться, что с одним уровнем оптимизации твой асм будет работать, а с другим - нет.
С этим я уже познакомился: например, в Debug не работает то, что работает в Release

Цитата Сообщение от DrOffset Посмотреть сообщение
А так же про всякие штуки типа выравнивания
А что именно знать надо? Пример можешь привести?
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
07.04.2014, 20:31 #4
Цитата Сообщение от mat_for_c Посмотреть сообщение
А что именно знать надо?
В общем случае это значит, что нужно знать как конкретный компилятор на конкретной платформе генерирует код.
Про выравнивание примеры есть по ссылке, много.
PS. Если ты надеешься выиграть в скорости таким образом - я тебя разочарую, вряд ли удастся обогнать компилятор, максимум сравняешься в скорости. Зато код будет непереносим и труден в сопровождении.

Добавлено через 10 минут
mat_for_c, вот, к примеру, я написал такой код для обнуления:
C++
1
2
3
4
5
void fill_raw(vector< vector<int> > & v)
{
    memset(&v[0][0], 0, v[0].size() * sizeof(int));
    memset(&v[1][0], 0, v[1].size() * sizeof(int));
}
из которого получилось вот это:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
_fill_raw:
    push    edi
    push    ebx
    mov ebx, DWORD PTR [esp+12]
    mov eax, DWORD PTR [ebx]
    mov edx, DWORD PTR [eax]
    mov ecx, DWORD PTR [eax+4]
    sub ecx, edx
    and ecx, -4
    xor eax, eax
    mov edi, edx
    rep stosb
    mov ecx, DWORD PTR [ebx]
    mov edx, DWORD PTR [ecx+12]
    mov ecx, DWORD PTR [ecx+16]
    sub ecx, edx
    and ecx, -4
    mov edi, edx
    rep stosb
    pop ebx
    pop edi
    ret
mingw32 c оптимизацией -02

Добавлено через 24 минуты
Теперь добавим цикл для общего случая:
C++
1
2
3
4
5
6
7
void fill_raw(vector< vector<int> > & v)
{
    for(int i = 0, s = v.size(); i < s; ++i)
    {
        memset(&v[i][0], 0, v[i].size() * sizeof(int));
    }
}
Получаем:
Кликните здесь для просмотра всего текста
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
_fill_raw:
    push    ebp
    push    edi
    push    esi
    push    ebx
    mov esi, DWORD PTR [esp+20]
    mov ecx, DWORD PTR [esi]
    mov eax, DWORD PTR [esi+4]
    sub eax, ecx
    sar eax, 2
    lea edx, [eax+eax*4]
    lea edx, [eax+edx*4]
    lea edx, [eax+edx*4]
    mov ebx, edx
    sal ebx, 8
    add edx, ebx
    mov ebx, edx
    sal ebx, 16
    add edx, ebx
    lea ebp, [eax+edx*2]
    xor edx, edx
    xor eax, eax
    test    ebp, ebp
    jg  L6
    jmp L2
L9:
    mov ecx, DWORD PTR [esi]
L6:
    lea ebx, [edx+edx*2]
    lea ecx, [ecx+ebx*4]
    mov ebx, DWORD PTR [ecx]
    mov ecx, DWORD PTR [ecx+4]
    sub ecx, ebx
    and ecx, -4
    mov edi, ebx
    rep stosb
    inc edx
    cmp edx, ebp
    jne L9
L2:
    pop ebx
    pop esi
    pop edi
    pop ebp
    ret

В принципе можно отталкиваться от приведенных примеров для написания своего (только с учетом компилятора и версии, конечно же) Но на самом деле я привел их для того, чтобы показать, что компилятор не дурак и код будет эффективен, если изначально правильно написан. А главное его можно будет перенести без проблем на другой компилятор.
1
mat_for_c
164 / 159 / 34
Регистрация: 26.04.2013
Сообщений: 724
Завершенные тесты: 3
07.04.2014, 22:10  [ТС] #5
DrOffset, попробовал так:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <vector>
#include <iostream>
#include <iterator>
 
using namespace std;
 
void main() {
   vector<vector<int>> v(2, vector <int> (3, 1));
   vector<vector<int>> v_copy = v;
 
   vector<vector<int>>::iterator ptr_v = v.begin();
 
   __asm {
      mov ecx, 2
 
      mov edi, ptr_v
      mov edi, [ptr_v]
        
      mov eax, v_copy 
      mov eax, [eax]
   cycl:
      mov dword ptr [edi + ecx*4], 0
      mov dword ptr [eax + ecx*4], 0
      loop cycl
   }
     
   for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 3; ++j)
         cout << v[i][j] << " ";
      cout << endl;
   }
 
   for (int i = 0; i < 2; ++i) {
      for (int j = 0; j < 3; ++j)
         cout << v_copy[i][j] << " ";
      cout << endl;
   }
}


почему когда делаешь через итератор, изменения не сохраняются ???
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
08.04.2014, 00:12 #6
mat_for_c, потому что так вообще нельзя делать. vector < vector <int> > - это ведь не просто двумерный массив. А итератор - это не просто указатель. И адрес его не обязан совпадать с адресом элемента. Вектор гарантирует только, что:
1) Память будет распределена непрерывной областью.
2) Операция взятия адреса от элемента даст адрес памяти в которой он находится.
&v[0] - адрес первого вектора vector<int>
&v[0][0] - адрес элемента int первого вектора.
Чтобы правильно адресовать элементы - нужно выяснить механизм адресации, который использует компилятор. Лучший способ это выяснить - декомпилировать программу с нормальным обращением (код на С++) к элементу.
0
mat_for_c
164 / 159 / 34
Регистрация: 26.04.2013
Сообщений: 724
Завершенные тесты: 3
08.04.2014, 19:08  [ТС] #7
DrOffset, через итераторы работает )). Это я не правильно написал:

Assembler
1
2
mov edi, [ptr_v] ; не так надо
mov edi, [edi] ; о как
и все изменения сохраняет
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
08.04.2014, 19:21 #8
Цитата Сообщение от mat_for_c Посмотреть сообщение
через итераторы работает ))
повезло.
Так зачем оно нужно-то?
0
mat_for_c
164 / 159 / 34
Регистрация: 26.04.2013
Сообщений: 724
Завершенные тесты: 3
08.04.2014, 20:50  [ТС] #9
Цитата Сообщение от DrOffset Посмотреть сообщение
зачем оно нужно-то?
хочу проверить, получится ли разогнать цикл или нет...

Спасибо за помощь )
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
08.04.2014, 22:09 #10
Цитата Сообщение от mat_for_c Посмотреть сообщение
хочу проверить, получится ли разогнать цикл или нет...
Используй memset вместо цикла. Твой асм код пока что медленнее, чем делает компилятор.
0
mat_for_c
164 / 159 / 34
Регистрация: 26.04.2013
Сообщений: 724
Завершенные тесты: 3
10.04.2014, 18:52  [ТС] #11
Цитата Сообщение от DrOffset Посмотреть сообщение
memset вместо цикла
не все так просто. мне нужно не все элементы обнулять, а большинство из них (примерно 80 - 90 % от размера вектора)

Цитата Сообщение от DrOffset Посмотреть сообщение
PS. Если ты надеешься выиграть в скорости таким образом - я тебя разочарую, вряд ли удастся обогнать компилятор, максимум сравняешься в скорости. Зато код будет непереносим и труден в сопровождении.
вот какая штука: протестил я програмки (c __asm и без) на

Intel core i5 M 460 2,53 Ghz и
AMD Phenom II X6 1035T Processor 2,60 GHz.

результаты:
14 сек __asm проиграл компилятору на Intel'е
~ 1 мин __asm выйграл компилятора на AMD
0
0x10
2478 / 1651 / 247
Регистрация: 24.11.2012
Сообщений: 4,087
10.04.2014, 18:56 #12
Цитата Сообщение от mat_for_c Посмотреть сообщение
протестил я програмки (c __asm и без)
Тут еще надо детально закапываться в то, как именно тестили. Кастануть бы на форум Андрея Аксенова - он в паре матерных фраз объяснил бы как надо бенчмаркать)
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
10.04.2014, 18:59 #13
Цитата Сообщение от mat_for_c Посмотреть сообщение
14 сек __asm проиграл компилятору на Intel'е
~ 1 мин __asm выйграл компилятора на AMD
А можно код бенчмарков посмотреть? Интересно же
0
mat_for_c
164 / 159 / 34
Регистрация: 26.04.2013
Сообщений: 724
Завершенные тесты: 3
10.04.2014, 19:05  [ТС] #14
Цитата Сообщение от DrOffset Посмотреть сообщение
можно код бенчмарков посмотреть
а что это ???

Добавлено через 2 минуты
Цитата Сообщение от 0x10 Посмотреть сообщение
Тут еще надо детально закапываться в то, как именно тестили
обычным способом: запускаем .exe и в самой программе через clock() замеряем время.
0
DrOffset
7376 / 4453 / 1009
Регистрация: 30.01.2014
Сообщений: 7,304
10.04.2014, 19:06 #15
mat_for_c, Тест производительности

Добавлено через 44 секунды
Цитата Сообщение от mat_for_c Посмотреть сообщение
обычным способом: запускаем .exe и в самой программе через clock() замеряем время.
Я думаю он тоже имел в виду код, а не способ замера (хотя это тоже важно).
0
10.04.2014, 19:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.04.2014, 19:06
Привет! Вот еще темы с ответами:

Обнулить четные элементы матрицы - C++
Обнулить четные элементы матрицы 1 7 6 0 2 3 9 5 0

Обнулить элементы матрицы A=176 - C++
Помогите пожалуйста написать программу на С++, буду очень благодарна. Обнулить элементы матрицы (176) над главной диагональю. ...

Обнулить нечетные элементы матрицы - C++
Помогите плз. Обнулить нечетные элементы матрицы |1 7 6| |0 2 3 | |9 5 0|

Массивы. Обнулить элементы столбцов - C++
Здравствуйте! Всю жизнь программировал на Паскале и вдруг си++...помогите пожалуйста с заданием, желательно с объяснением, ибо чайник...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru